Upgrade to Pro — share decks privately, control downloads, hide ads and more …

RDBのインデックス完全に理解する

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for Tada Tada
October 29, 2024
75

 RDBのインデックス完全に理解する

RDBのインデックス完全に理解します

Avatar for Tada

Tada

October 29, 2024
Tweet

Transcript

  1. RDBの仕組みその① • ある100万人いる巨大な表がある • 表をSQLで検索する • SELECT name WHERE name=’多田信洋’

    FROM Users • この時100万行全てを読まずに見つける方法は? ユーザー名 ユーザーID 多田 信洋 1 田中太郎 2 織田信長 3 … …
  2. いろいろと実験 • テーブルの説明 • 作成したテーブルは簡単な構造 • Idとnameとageのみの単純なテーブル • レコードは1000万件 •

    レコードの挿入は1万レコード2000msから2500ms程度 • インデックスをnameとageに作成した後では1万レコード3000msから 3500msほど
  3. 全件取得 • SELECT COUNT(*) FROM staffs; • 2.17s • CREATE

    INDEX age ON staffs; (年齢にインデックスを貼る) • 15.6s • もう一度SELECT COUNT(*) FROM staffs; • 2.04s
  4. Whereによる絞り込み age<10名レコードは100万件中9万件 • SELECT COUNT(*) FROM staffs WHERE age<10; (INDEXなし)

    • 2.09s • CREATE INDEX age ON staffs(age); • SELECT COUNT(*) FROM staffs WHERE age<10; • 0.28s • インデックスを貼ると早くなった
  5. LIKE句による比較 • SELECT COUNT(*) FROM staffs WHERE name LIKE ’a%’;

    • 2.045s • CREATE INDEX name ON staffs (name); (インデックスを貼る) • SELECT COUNT(*) FROM staffs WHERE name LIKE ’a%’; • 1.972s (効果なし!!) • CREATE INDEX name2 ON staffs (name text_pattern_ops); • SELECT COUNT(*) FROM staffs WHERE name LIKE ’a%’; • 0.198s ロケールの設定次第では前方一致にインデックスが効かない
  6. LIKE句を使った比較2 • SELECT COUNT(*) FROM staffs WHERE name LIKE ‘ab%cd’

    • これは’ab%’までの前方一致が効く 0.09s • SELECT COUNT(*) FROM staffs WHERE name LIKE ‘%cd’ • 後方一致には全く効果がない 2.04s
  7. EXPLAINの話 • EXPLAIN SELECT name FROM staffs WHERE age=50 ORDER

    BY name; • どのインデックスを使うか? • どのように実行をするつもりか?がわかる。 • 詳細は置いといて、costを比較すれば改善したかどうかがわかる
  8. 複合インデックス① • インデックス無し • EXPLAIN SELECT name FROM staffs WHERE

    age=50 ORDER BY name; • age=50 のものを探索 した後にソートしている。
  9. 複合インデックス② • ageにインデックスを貼った場合 • EXPLAIN SELECT name FROM staffs WHERE

    age=50 ORDER BY name; • age=50 のものをインデックスを用いて探索 した後にソートしている。 • Costは128993から77094に下がっている
  10. 複合インデックス③ • age,nameの順にインデックスを貼った場合 • EXPLAIN SELECT name FROM staffs WHERE

    age=50 ORDER BY name; • age=50 かつソート済みのものをインデックスを用いて探索 するだけ。 • Costは128993から30322に下がっている
  11. 軽い説明 • Nested Loop • JOIN時に1つ目のテーブルの各列に合わせて2つ目のテーブルを全捜査 • Bitmap Heap Scan

    • 動的にBitmapを構築してスキャン • Bitmap Index Scan • Indexを用いてBitmapスキャンする • OR演算など簡単でないクエリで使用
  12. やめた方がいいこと • カーディナリティの低い列にインデックスを貼る • 良かれと思って貼ったのに書き込みが遅くなるだけ • SQL中で演算を行う • SELECT *

    FROM staffs WHERE age*2=100; • ↑のように演算が入るとインデックスが効かない • 暗黙の型変換を行う • 上記の演算と同じ