SlideShare a Scribd company logo
matsuu / qpstudy
20130728
インデックス使えてる?
じぇじぇじぇ!
● まつうです
○ hatena tmatsuu
○ twitter matsuu
○ 32歳ぐらい
● インフラエンジニアだけど元プログラマ
○ SQL好きです
○ PostgreSQL派(だけど仕事はMySQLをよく使う)
○ 仕事でチューニングやることもある
● 今日は懇親会のみ参加です
○ 勉強会の内容とかぶってたらごめんなさい
● じぇじぇとか言ってるけど朝ドラ見てない
○ じぇじぇはNHKの朝ドラ「あまちゃん」のネタです
自己紹介?じぇじぇ!
突然ですが…
クイズです
じぇじぇじぇ!
クイズの内容
● インデックスに関するクイズを3問だすよ
○ 特に景品などは用意してません
○ MySQLとPostgreSQLを想定しています
● 人の褌で相撲を取ってるよ
○ 元ネタは http://use-the-index-luke.com/3-minute-test
● 社内勉強会の使い回しネタだよ
○ じぇじぇじぇ!すみません
● 間違い等あれば適宜指摘して下さい
○ じぇじぇじぇ!ごめんなさい
インデックスとは(Wikipedia引用)
http://ja.wikipedia.org/wiki/%E7%B4%A2%E5%BC%95_(%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%
B9)
データベースの分野において、索引(さくいん)またはインデック
ス (英: index) は、表への処理を高速化するためのデータ構
造。索引は表の中の1個以上の列を対象に作成され、ランダム
な参照処理や一定の順序でのレコードへのアクセスの効率を
高めることができる。
ざっくりとしたインデックス作成方法
CREATE INDEX インデックス名 ON テーブル名(カラム,...);
(例)
2013年7月28日に作成された記事一覧を取得する
SELECT * FROM 記事 WHERE 作成日 = '2013-07-28';
→作成日にインデックスを張る
CREATE INDEX 作成日idx ON 記事 (作成日);
クイズ その1
2012年に作成された記事一覧を取得したい
SELECT * FROM 記事 WHERE year(作成日) = 2012;
次のようなインデックスを作ると効果があるか?
CREATE INDEX i1 ON 記事 (作成日);
● 速くなる
● 速くなるが、もっと良い方法がある
● 速くならない
※PostgreSQLの場合はyear(作成日)→date_part('year', 作成日)
クイズ その1こたえ
2012年に作成された記事一覧を取得したい
SELECT * FROM 記事 WHERE year(作成日) = 2012;
次のようなインデックスを作ると効果があるか?
CREATE INDEX i1 ON 記事 (作成日);
×速くなる
×速くなるが、もっと良い方法がある
○速くならない
じぇじぇじぇ!
作成日にインデックスが張られていても、YEAR(作成日)にインデックスは使われな
い。
クイズ その1対策
● 関数にインデックスを張る
CREATE INDEX i2 ON 記事 (YEAR(作成日));
→MySQLではできません
● BETWEENを使う
SELECT タイトル FROM 記事 WHERE 作成日 BETWEEN
'2012-01-01' AND '2012-12-31';
● 作成年を用意する
ALTER TABLE 記事 ADD COLUMN 作成年 INTEGER;
CREATE INDEX i3 ON 記事 (作成年);
→記事を新規作成・更新した際に作成年のケアが必要
→冗長で美しくないけどね
クイズ その2
カテゴリが「仕事」の最新の記事を1件取得したい
SELECT * FROM 記事 WHERE カテゴリ = '仕事'
ORDER BY 作成日 DESC LIMIT 1;
次のようなインデックスを作ると効果があるか?
CREATE INDEX i4 ON 記事 (カテゴリ, 作成日);
● 速くなる
● 速くなるが、もっと良い方法がある
● 速くならない
クイズ その2こたえ
カテゴリが「仕事」の最新の記事を1件取得したい
SELECT * FROM 記事 WHERE カテゴリ = '仕事'
ORDER BY 作成日 DESC LIMIT 1;
次のようなインデックスを作ると効果があるか?
CREATE INDEX i4 ON 記事 (カテゴリ, 作成日);
○速くなる
×速くなるが、もっと良い方法がある
×速くならない
じぇじぇじぇ!
クイズ その2補足
CREATE INDEXのカラムにはカラムを逆順に並べるオプション
DESCが存在する
CREATE INDEX i4 ON 記事 (カテゴリ, 作成日 DESC);
がしかし、今回のようなSQLであれば、DESCをつけてもつけな
くても応答時間は変わらない
ORDER BYにカラムが複数あり、ソート順が異なるのであれば
効果あり
(例)ORDER BY 優先度 DESC, 作成日
※ちなみにMySQLではDESCをつけても無視されれ常にASC(MySQL 5.6現在)
クイズ その3
カテゴリと投稿者で記事を絞り込みたい
1. SELECT * FROM 記事 WHERE 投稿者 = 'iara' AND カテゴリ = '勉強会';
2. SELECT * FROM 記事 WHERE 投稿者 = 'matsuu';
3. SELECT * FROM 記事 WHERE カテゴリ = 'エンタメ';
次のようなインデックスを作ると効果があるか?
CREATE INDEX i5 ON 記事 (カテゴリ, 投稿者);
● 1は速くなる?変わらない?
● 2は速くなる?変わらない?
● 3は速くなる?変わらない?
クイズ その3こたえ
カテゴリと投稿者で記事を絞り込みたい
1. SELECT * FROM 記事 WHERE 投稿者 = 'iara' AND カテゴリ = '勉強会';
2. SELECT * FROM 記事 WHERE 投稿者 = 'matsuu';
3. SELECT * FROM 記事 WHERE カテゴリ = 'エンタメ';
次のようなインデックスを作ると効果があるか?
CREATE INDEX i5 ON 記事 (カテゴリ, 投稿者);
● 1は速くなる
● 2は変わらない
● 3は速くなる
じぇじぇじぇ!
クイズ その3補足
CREATE INDEX i5 ON 記事 (カテゴリ, 投稿者);
インデックスのカラムの順番には意味がある
● 検索条件がカテゴリ→OK
● 検索条件がカテゴリと投稿者→OK
● 検索条件が投稿者→NG
● 検索条件がカテゴリとタイトル→カテゴリだけOK
投稿者のみの検索も行うなら以下も追加するのもアリかと
CREATE INDEX i6 ON 記事 (投稿者);
インデックスマージってのも一応あるよ
いかがでしたか
クイズ終了
まとめ
● SELECTが遅いようであればインデックスを
張ってみよう
○ 効果があるかきちんと確認すべし
○ 張りすぎはINSERT等が重くなるので注意
● まず検証環境を用意しましょう
○ 応答が遅くなったりするので影響がないように
○ データの内容や行数によっても変化するので本番とほ
ぼ同じデータを用意するのがいいよ
● 詳しくはUse The Index, Luke!を参照
○ http://use-the-index-luke.com/
○ 日本語の資料でいいのあれば教えてほしい
ご清聴
ありがとうございました

More Related Content

インデックス使えてる?じぇじぇじぇ!