Mysql 5.6の「暗黙的な変換」により、インデックスの障害と不正確なデータが発生しました

バックグラウンド

  • SQlクエリ中に、where条件のvacharタイプフィールドの単一引用符クエリを削除しようとしましたが、この時点で、高速であるはずのこの文は実際には非常に遅いことがわかりました。このvarcharフィールドには複合インデックスがあります。アイテムの総数は58,989であり、一重引用符なしで見つかったデータでさえ、必要なデータではありません。
  • mysql 5.6バージョン、innoDBエンジンを使用

実情は以下の通りです

  • 実行結果を見てみましょう
    ここに写真の説明を挿入

  • 上記の説明では、それに注意する必要があります。where条件の文字列は、一重引用符のない完全な数値でなければなりません。それ以外の場合はエラーを報告します
    ここに写真の説明を挿入

  • 見つかったデータが必要なデータではない可能性もあります。以下に示すように

ここに写真の説明を挿入

分析

  1. 実行結果から判断すると、対応するインデックスは一重引用符で消えています。一重引用符を使用しない場合、インデックスはなく、テーブル全体のスキャンが実行されます。
  2. なぜそうなのですか?mysqlオプティマイザが型変換を直接実行しないのはなぜですか?
  • SQLステートメントに一重引用符が導入されているということは、このタイプが文字列データタイプのCHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM、およびSETであることを意味します。
  • 一重引用符がない場合は、これがint、bigDecimalなどの文字列以外のタイプであることを意味します。
  • サブタイトルと特殊記号の文字列に一重引用符が追加されていない場合、結果として型変換が失敗し、SQlを実行できなくなります。上記のように:
1054 - Unknown column '000w1993521' in 'where clause', Time: 0.008000s
  1. まず、SQLの実行プロセスを見てみましょう。
    ここに写真の説明を挿入

(ネットマップ)

  • 最初に結論に達しました。インデックスフィールドで関数操作を実行すると(この場合、キャスト関数は暗黙的な変換を実行します)、インデックス値の順序が破壊される可能性があるため、オプティマイザーはツリー検索関数を破棄することを決定します。(Https://dev.mysql.com/doc/refman/5.7/en/cast-functions.html)
    [外部リンク画像の転送に失敗しました。ソースサイトにリーチ防止リンクメカニズムがある可能性があります。画像を保存して直接アップロードすることをお勧めします(img -l5AwT0xu-1607244327891)(http://note.youdao.com/yws/res/23689/CE6F785994E6476D816B23787CE65217)]の
    意味:BINARY、CAST()、またはCONVERT()を使用してインデックス列を変換する場合は、MySQLインデックスが有効に使用されていない可能性があります。
  • 検出されたデータの不正確さは、暗黙の変換によるものでもあり、変換後に異なる数値タイプが生成され、不等式が等しくなります。

暗黙の変換

1.生産条件

  1. 演算子を異なるタイプのオペランドで使用すると、タイプ変換が行われ、オペランドに互換性があります。暗黙の変換
  2. 暗黙的な変換の条件:
    • 2つのパラメータの少なくとも1つがNULLの場合、比較の結果もNULLになります。例外は、<=>を使用して2つのNULLを比較すると、1が返されることです。どちらの場合も、型変換は必要ありません。
    • 両方のパラメーターは文字列であり、型変換なしで文字列に従って比較されます
    • 両方のパラメーターは整数であり、型変換なしで整数に従って比較されます
    • 16進値を非数値と比較すると、バイナリ文字列として扱われます。
    • 1つのパラメーターはTIMESTAMPまたはDATETIMEであり、もう1つのパラメーターは定数であり、定数はタイムスタンプに変換されます
    • 一方のパラメータは10進型で、もう一方のパラメータが10進または整数の場合、整数は比較のために10進に変換され、もう1つのパラメータが浮動小数点数の場合、10進は比較のために浮動小数点に変換されます。
    • 他のすべての場合、2つのパラメーターは浮動小数点数に変換されてから比較されます

2.実際の状況を分析します

  1. 上記の例は、他の状況に属する整数と文字列の比較です。次に、最初にインデックスの失敗の理由を分析しましょう
    1. 暗黙的な変換の他のケースのため、比較値は比較のために浮動小数点数に変換する必要があります
    2. 最初にクエリ条件の値を浮動小数点数に変換してから、テーブルのレコード値を変換します。これにより、この時間より前に作成されたインデックスの並べ替えは有効になりません。暗黙の変換(関数)によって元の値が変更されたため、オプティマイザはここではインデックスを直接使用せず、テーブル全体のスキャンを直接使用すると言われています。
  2. 上記のクエリ結果のように、一致しない値(または部分的に一致する値)をクエリします。これは、MYsq​​lの暗黙的な変換ルールであるソースコードを実際に確認する必要があります。ここでは詳しく分析しません(関連するドキュメントが見つからないため)。
    歴史的な理由から、古いデザインとの互換性が必要です。MySQLの型変換関数castおよびconvertを使用して、明示的に変換できます。

総括する

  1. 暗黙的な変換と関数を使用すると、インデックスに障害が発生し、選択したデータが不正確になります
  2. 暗黙的な変換の条件とルール
  3. 暗黙的な変換が原因でインデックスが失敗する具体的な理由は、比較値を型変換する必要があり、インデックスが無効であるためです。
  4. 暗黙的な型変換は避けてください。暗黙的な変換の種類には、主に一貫性のないフィールドタイプが含まれ、パラメータには複数の型、文字セットタイプ、または一貫性のない照合ルールなどが含まれます。

参照

  • https://dev.mysql.com/doc/refman/5.7/en/type-conversion.html
  • https://xiaomi-info.github.io/2019/12/24/mysql-implicit-conversion/
  • https://zhuanlan.zhihu.com/p/95170837

おすすめ

転載: blog.csdn.net/weixin_40413961/article/details/110743406