定数値が範囲外であるか、カラムタイプに関して間違ったタイプである定数とカラム値の比較は、クエリーの最適化中に、実行中ではなく行単位で処理されるようになりました。 この方法で処理できる比較は、>
, >=
, <
, <=
, <>
/!=
、=
および <=>
です。
次のステートメントで作成されたテーブルについて考えてみます:
CREATE TABLE t (c TINYINT UNSIGNED NOT NULL);
クエリー SELECT * FROM t WHERE c < 256
の WHERE
条件に、TINYINT UNSIGNED
カラムの範囲外の整数定数 256 が含まれています。 これまでは、両方のオペランドを大きい型として扱うことで処理されていましたが、c
に許可されている値が定数より小さいため、かわりに WHERE
式を WHERE 1
として折りたたんで、クエリーを SELECT * FROM t WHERE 1
としてリライトできます。
これにより、オプティマイザは WHERE
式を完全に削除できます。 カラム c
が NULL 値可能だった (つまり、TINYINT UNSIGNED
としてのみ定義されていた) 場合、クエリーは次のようにリライトされます:
SELECT * FROM t WHERE ti IS NOT NULL
折りたたみは、サポートされている MySQL カラムタイプと比較して、次のように定数に対して実行されます:
-
整数カラムタイプ. 整数型は、次に説明するように、次の型の定数と比較されます:
-
整数値. 定数がカラムタイプの範囲外の場合、すでに示すように、比較は
1
またはIS NOT NULL
に折りたたまれます。定数が範囲境界の場合、比較は
=
に折りたたまれます。 次に例を示します (すでに定義されているのと同じテーブルを使用):mysql> EXPLAIN SELECT * FROM t WHERE c >= 255; *************************** 1. row *************************** id: 1 select_type: SIMPLE table: t partitions: NULL type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 5 filtered: 20.00 Extra: Using where 1 row in set, 1 warning (0.00 sec) mysql> SHOW WARNINGS; *************************** 1. row *************************** Level: Note Code: 1003 Message: /* select#1 */ select `test`.`t`.`ti` AS `ti` from `test`.`t` where (`test`.`t`.`ti` = 255) 1 row in set (0.00 sec)
-
浮動小数点値または固定小数点値. 定数が小数型 (
DECIMAL
,REAL
,DOUBLE
、FLOAT
など) のいずれかで、小数部がゼロ以外の場合は等しくできません。それに応じて折りたたみます。 その他の比較の場合は、符号に従って整数値に切り上げまたは切り下げてから、整数比較ですでに説明されている範囲チェックおよびハンドルを実行します。小さすぎて
DECIMAL
として表現できないREAL
値は、記号に応じて .01 または -.01 に丸められ、DECIMAL
として処理されます。 文字列型. 文字列値を整数型として解釈し、整数値間の比較を処理します。 これが失敗した場合は、値を
REAL
として処理してみてください。
-
-
DECIMAL または REAL カラム. ここで説明するように、小数型は次の型の定数と比較されます:
整数値. カラム値の整数部分に対して範囲チェックを実行します。 折りたたみ結果がない場合は、定数をカラム値と同じ小数点以下の桁数で
DECIMAL
に変換し、DECIMAL
として確認します (次を参照)。-
DECIMAL または REAL 値. オーバーフローをチェックします (つまり、定数の整数部分に、カラムの小数型に許可されている桁数より多い数値があるかどうか)。 その場合は折りたたみます。
定数の小数点以下の桁数がカラムの型より多い場合は、定数を切り捨てます。 比較演算子が
=
または<>
の場合は、折りたたみます。 演算子が>=
または<=
の場合は、切捨てのために演算子を調整します。 たとえば、カラムタイプがDECIMAL(3,1)
の場合、SELECT * FROM t WHERE f >= 10.13
はSELECT * FROM t WHERE f > 10.1
になります。定数の小数点以下の桁数がカラムの型より少ない場合は、同じ桁数の定数に変換します。
REAL
値のアンダーフロー (小数が少なすぎて表すことができない) の場合は、定数を小数 0 に変換します。 文字列値. 値を整数型として解釈できる場合は、そのように処理します。 それ以外の場合は、
REAL
として処理してください。
-
FLOAT または DOUBLE カラム. 定数と比較した
FLOAT(
またはm
,n
)DOUBLE(
の値は、次のように処理されます:m
,n
)値がカラムの範囲をオーバーフローする場合は、折りたたみます。
値の小数点以下が
n
を超える場合は、折りたたみ時に切り捨てて補正します。=
と<>
の比較の場合は、前述のようにTRUE
、FALSE
またはIS [NOT] NULL
に折りたたみます。他の演算子の場合は、演算子を調整します。値が
m
整数より大きい場合は折りたたみます。
制限. この最適化は、次の場合には使用できません:
BETWEEN
またはIN
を使用した比較。日付型または時間型を使用する
BIT
のカラムまたはカラム。プリペアドステートメントの準備フェーズ中。ただし、プリペアドステートメントが実際に実行されるときに最適化フェーズ中に適用できます。 これは、ステートメントの準備中に定数の値が不明であるためです。