シングルパートインデックスでは、インデックス値インターバルはWHERE
節内の対応する状態で表現されます。よって「インターバル」よりもrange
状態が使用されます。
シングルパートインデックスのためのrange状態の定義は以下のとおりです。
BTREE
とHASH
の両インデックスにとって、=
,
<=>
、IN
、IS
NULL
、またはIS NOT
NULL
演算子を使用した際の定数値の主部分の比較はrange状態です。
BTREE
インデックスにとって、>
、<
,
>=
、<=
,
BETWEEN
、!=
、<>
演算子、またはLIKE
'
(pattern
''
がワイルドカードで始まらないとき)を使用しての定数値の主部分の比較は、range状態です。
pattern
'
全インデックスの種類にとって、OR
またはAND
で結合されたマルチレンジ状態は、あるレンジ状態を形成します。
先の説明の 「定数値」は以下の1つを意味しています。
クエリ文字列の定数
同じ結合のconst
またはsystem
テーブルのカラム
相関しないサブクエリの結果
以前の型のサブ表現からのみ生成された表現
ここにWHERE
節内でレンジ状態のクエリの例を以下に示します。
SELECT * FROM t1 WHEREkey_col
> 1 ANDkey_col
< 10; SELECT * FROM t1 WHEREkey_col
= 1 ORkey_col
IN (15,18,20); SELECT * FROM t1 WHEREkey_col
LIKE 'ab%' ORkey_col
BETWEEN 'bar' AND 'foo';
非定数値が定数伝播フェーズ中に定数に変換されることに留意してください。
MySQLはWHERE
節から、各インデックスよりレンジ状態を抽出しようとします。抽出プロセスの最中、レンジ状態を生成することができない状態は破棄され、重複するレンジを生成する状態は結合され、そして空のレンジを生成する状態は取り除かれます。
key1
がインデックスカラムでnonkey
がインデックスカラムでない、下記のステートメントを考慮に入れてください。
SELECT * FROM t1 WHERE (key1 < 'abc' AND (key1 LIKE 'abcde%' OR key1 LIKE '%b')) OR (key1 < 'bar' AND nonkey = 4) OR (key1 < 'uux' AND key1 > 'z');
key1
の抽出プロセスは以下のとおりです。
オリジナルのWHERE
節で始めてください。
(key1 < 'abc' AND (key1 LIKE 'abcde%' OR key1 LIKE '%b')) OR (key1 < 'bar' AND nonkey = 4) OR (key1 < 'uux' AND key1 > 'z')
nonkey = 4
とkey1 LIKE
'%b'
はレンジスキャンに使用できませんので、取り除いてください。TRUE
と置き換えることが、正しく取り除く方法です。こうすることによって、レンジスキャン中に適合する行を見落としません。TRUE
で置き換えたとき、以下になります。
(key1 < 'abc' AND (key1 LIKE 'abcde%' OR TRUE)) OR (key1 < 'bar' AND TRUE) OR (key1 < 'uux' AND key1 > 'z')
常に真か偽のコラップス状態
(key1 LIKE 'abcde%' OR
TRUE)
は常に真です
(key1 < 'uux' AND key1 >
'z')
は常に偽です
定数でこれらの状態を置き換えると、以下になります。
(key1 < 'abc' AND TRUE) OR (key1 < 'bar' AND TRUE) OR (FALSE)
不必要なTRUE
とFALSE
定数を取り除くことで、以下になります。
(key1 < 'abc') OR (key1 < 'bar')
重複するインターバルを1つに結合することでレンジスキャンで使用できる最終状態が生成されます。
(key1 < 'bar')
一般的にレンジスキャンで使用される状態は(そして前の例で説明されたとおり)、WHERE
節よりも制限されません。MySQLはレンジ条件を満たすが、WHERE
節を完全に満たさない行にフィルタをかけるために追加でチェックを行います。
レンジ条件抽出アルゴリズムは任意のデプスの入れ子
AND
/OR
生成子を取り扱うことができ、その出力はWHERE
節内でどの順序で条件が現れるかに影響されません。