Documentation Home
MySQL 8.0 リファレンスマニュアル
Download this Manual
PDF (US Ltr) - 36.1Mb
PDF (A4) - 36.2Mb


このページは機械翻訳したものです。

8.2.1.14 定数 - フォールディングの最適化

定数値が範囲外であるか、カラムタイプに関して間違ったタイプである定数とカラム値の比較は、クエリーの最適化中に、実行中ではなく行単位で処理されるようになりました。 この方法で処理できる比較は、>, >=, <, <=, <>/!== および <=> です。

次のステートメントで作成されたテーブルについて考えてみます:

CREATE TABLE t (c TINYINT UNSIGNED NOT NULL);

クエリー SELECT * FROM t WHERE c < 256WHERE 条件に、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, DOUBLEFLOAT など) のいずれかで、小数部がゼロ以外の場合は等しくできません。それに応じて折りたたみます。 その他の比較の場合は、符号に従って整数値に切り上げまたは切り下げてから、整数比較ですでに説明されている範囲チェックおよびハンドルを実行します。

      小さすぎて DECIMAL として表現できない REAL 値は、記号に応じて .01 または -.01 に丸められ、DECIMAL として処理されます。

    • 文字列型.  文字列値を整数型として解釈し、整数値間の比較を処理します。 これが失敗した場合は、値を REAL として処理してみてください。

  • DECIMAL または REAL カラム.  ここで説明するように、小数型は次の型の定数と比較されます:

    • 整数値.  カラム値の整数部分に対して範囲チェックを実行します。 折りたたみ結果がない場合は、定数をカラム値と同じ小数点以下の桁数で DECIMAL に変換し、DECIMAL として確認します (次を参照)。

    • DECIMAL または REAL 値.  オーバーフローをチェックします (つまり、定数の整数部分に、カラムの小数型に許可されている桁数より多い数値があるかどうか)。 その場合は折りたたみます。

      定数の小数点以下の桁数がカラムの型より多い場合は、定数を切り捨てます。 比較演算子が = または <> の場合は、折りたたみます。 演算子が >= または <= の場合は、切捨てのために演算子を調整します。 たとえば、カラムタイプが DECIMAL(3,1) の場合、SELECT * FROM t WHERE f >= 10.13SELECT * FROM t WHERE f > 10.1 になります。

      定数の小数点以下の桁数がカラムの型より少ない場合は、同じ桁数の定数に変換します。 REAL 値のアンダーフロー (小数が少なすぎて表すことができない) の場合は、定数を小数 0 に変換します。

    • 文字列値.  値を整数型として解釈できる場合は、そのように処理します。 それ以外の場合は、REAL として処理してください。

  • FLOAT または DOUBLE カラム.  定数と比較した FLOAT(m,n) または DOUBLE(m,n) の値は、次のように処理されます:

    値がカラムの範囲をオーバーフローする場合は、折りたたみます。

    値の小数点以下が n を超える場合は、折りたたみ時に切り捨てて補正します。 =<> の比較の場合は、前述のように TRUEFALSE または IS [NOT] NULL に折りたたみます。他の演算子の場合は、演算子を調整します。

    値が m 整数より大きい場合は折りたたみます。

制限.  この最適化は、次の場合には使用できません:

  1. BETWEEN または IN を使用した比較。

  2. 日付型または時間型を使用する BIT のカラムまたはカラム。

  3. プリペアドステートメントの準備フェーズ中。ただし、プリペアドステートメントが実際に実行されるときに最適化フェーズ中に適用できます。 これは、ステートメントの準備中に定数の値が不明であるためです。