2章: where句
8.範囲検索(大なり小なり)
1. 範囲検索で最も重要な点
INDEX RANGE SCAN のコストの大半はリーフノードの走査量で決まる。
したがって、インデックスをスキャンする範囲をいかに狭くできるかが性能を左右する。
2. 実際の性能差は「選択性」で決まる
パフォーマンスの違いは
- データ分布
- 検索条件の選択性
に強く依存する
例:
date_of_birthの範囲が狭い
→ どの列順でも差は小さい
- 日付範囲が広い
→ 列順の違いがそのまま性能差になる
3. 実行計画で見るべきポイント:述語情報
Oracleの実行計画には、述語情報として以下が表示される。
- アクセス述語(Access Predicate)
- フィルタ述語(Filter Predicate)
これを見ることで、
データベースが WHERE 句の条件を
「どの段階で」「どのように」使っているか
が分かる。
4. アクセス述語とフィルタ述語の違い(重要)
アクセス述語
- インデックス走査の 開始点と終了点 を決める
- インデックスをスキャンする範囲を定義
- 範囲を狭められるのはこれだけ
フィルタ述語
- リーフノード走査後に適用
- インデックスのスキャン範囲は狭められない
- 読んだ後に捨てるだけ
5. 列順による述語の違い(整理)
インデックス (date_of_birth, subsidiary_id)
-
アクセス述語:
date_of_birth -
フィルタ述語:
subsidiary_id
➡ 日付範囲だけがスキャン範囲を決定
子会社IDは後段評価
インデックス (subsidiary_id, date_of_birth)
-
アクセス述語:
subsidiary_id
date_of_birth -
フィルタ述語:
なし
➡ WHERE句のすべての条件が、スキャン範囲を決定
6. BETWEEN 演算子について
BETWEEN は下限・上限 両方を含む
WHERE date_of_birth
BETWEEN DATE '1971-01-01' AND DATE '1971-01-10';
以下と同義:
date_of_birth >= DATE '1971-01-01'
AND date_of_birth <= DATE '1971-01-10'
- 範囲検索としての性質は同じ
- インデックスの使われ方も変わらない
7. 設計指針(最重要)
1. 等価条件(=)を先頭に
2. 範囲条件(>, <, BETWEEN)を後ろに
3. アクセス述語が最大になるように列順を決める
4. フィルタ述語だけになる条件は
インデックス設計上の効果が小さい
まとめ
範囲検索の性能は、
アクセス述語によって決まるインデックス走査範囲の大きさで決まり、
その範囲を最小化する列順設計が最重要である。