📣

TiDB Cloud Serverless が
Starter
に変わりました!このページは自動翻訳されたものです。
原文はこちらからご覧ください。

暗黙的な型変換を避ける

このドキュメントでは、TiDB における暗黙的な型変換のルールと考えられる結果、および暗黙的な型変換を回避する方法について説明します。

変換ルール

SQL ステートメントの述語の両側のデータ型が一致しない場合、TiDB は、述語操作のために、片側または両側のデータ型を互換性のあるデータ型に暗黙的に変換します。

TiDB における暗黙的な型変換のルールは次のとおりです。

  • 引数の一方または両方がNULL場合、比較の結果はNULLなります。NULL 安全な<=>比較演算子は変換を必要としません。NULL <=> NULL はtrueになります。
  • 比較演算の両方の引数が文字列の場合、それらは文字列として比較されます。
  • 両方の引数が整数の場合、それらは整数として比較されます。
  • 数値と比較しない場合は、16 進数値はバイナリ文字列として扱われます。
  • 引数の一方が小数値の場合、比較はもう一方の引数に依存します。もう一方の引数が小数値または整数値の場合、その引数は小数値と比較されます。もう一方の引数が浮動小数点値の場合、その引数は浮動小数点値と比較されます。
  • 引数の 1 つがTIMESTAMP列またはDATETIME列で、もう 1 つの引数が定数の場合、比較が実行される前に定数はタイムスタンプに変換されます。
  • それ以外の場合、引数は浮動小数点数 ( DOUBLE型) として比較されます。

暗黙的な型変換によって生じる結果

暗黙的な型変換は、人間とコンピュータのインタラクションの利便性を向上させます。ただし、アプリケーションコードでは暗黙的な型変換の使用は避けてください。以下の問題が発生する可能性があります。

  • インデックスの無効性
  • 精度の低下

インデックスの無効性

以下のケースでは、主キーはaccount_idで、そのデータ型はvarcharです。実行プランでは、このSQL文には暗黙的な型変換があり、インデックスを使用できません。

DESC SELECT * FROM `account` WHERE `account_id`=6010000000009801; +-------------------------+----------------+-----------+---------------+------------------------------------------------------------+ | id | estRows | task | access object | operator info | +-------------------------+----------------+-----------+---------------+------------------------------------------------------------+ | TableReader_7 | 8000628000.00 | root | | data:Selection_6 | | └─Selection_6 | 8000628000.00 | cop[tikv] | | eq(cast(findpt.account.account_id), 6.010000000009801e+15) | | └─TableFullScan_5 | 10000785000.00 | cop[tikv] | table:account | keep order:false | +-------------------------+----------------+-----------+---------------+------------------------------------------------------------+ 3 rows in set (0.00 sec)

実行結果の簡単な説明: 上記の実行プランから、 Cast演算子が表示されます。

精度の低下

以下のケースでは、フィールドaのデータ型はdecimal(32,0)です。実行プランでは暗黙的な型変換が発生し、decimal フィールドと文字列定数の両方が double 型に変換されます。double 型の精度はdecimal 型ほど高くないため、精度が低下します。この場合、SQL文は結果セットを範囲外として誤ってフィルタリングします。

DESC SELECT * FROM `t1` WHERE `a` BETWEEN '12123123' AND '1111222211111111200000'; +-------------------------+---------+-----------+---------------+-------------------------------------------------------------------------------------+ | id | estRows | task | access object | operator info | +-------------------------+---------+-----------+---------------+-------------------------------------------------------------------------------------+ | TableReader_7 | 0.80 | root | | data:Selection_6 | | └─Selection_6 | 0.80 | cop[tikv] | | ge(cast(findpt.t1.a), 1.2123123e+07), le(cast(findpt.t1.a), 1.1112222111111112e+21) | | └─TableFullScan_5 | 1.00 | cop[tikv] | table:t1 | keep order:false, stats:pseudo | +-------------------------+---------+-----------+---------------+-------------------------------------------------------------------------------------+ 3 rows in set (0.00 sec)

実行結果の簡単な説明: 上記の実行プランから、 Cast演算子が表示されます。

SELECT * FROM `t1` WHERE `a` BETWEEN '12123123' AND '1111222211111111200000'; +------------------------+ | a | +------------------------+ | 1111222211111111222211 | +------------------------+ 1 row in set (0.01 sec)

実行結果の簡単な説明: 上記の実行では間違った結果が生成されます。

ヘルプが必要ですか?

不和またはスラック 、あるいはサポートチケットを送信するについてコミュニティに質問してください。

このページは役に立ちましたか?