MySQL 5.6 の「暗黙的な変換」によりインデックスが失敗し、データが不正確になる

MySQL 5.6 の「暗黙的な変換」によりインデックスが失敗し、データが不正確になる

背景

  • SQL クエリを実行するときに、where 条件の vachar 型フィールドの単一引用符を削除しようとしました。このとき、非常に高速であるはずのこのステートメントが、実際には非常に遅いことがわかりました。この varchar フィールドには複合インデックスがあります。エントリの合計数は 58989 であり、一重引用符がない場合でも、取得されるデータは必要なデータではありません。
  • MySQL 5.6バージョンを使用しており、innoDBエンジンの実際の状況は以下のとおりです

実行結果を見てみましょう

ここに画像の説明を挿入

上記の説明では、where 条件内の文字列はすべて一重引用符なしの数字でなければならないことにも注意する必要があります。そうでなければエラーが報告されます

ここに画像の説明を挿入

見つかったデータが、必要なデータではない可能性もあります。下記の通り

ここに画像の説明を挿入

分析する

  1. 実行結果から、対応するインデックスが一重引用符で使用されていることがわかります。一重引用符がない場合、インデックスは使用されず、テーブル全体のスキャンが実行されます。
  2. なぜこのようなことが起こるのでしょうか? MySQL のオプティマイザが型変換を直接実行しないのはなぜですか?
  • SQL ステートメントに一重引用符を使用すると、その型が文字列データ型 CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM、および SET であることを示します。 。
  • 一重引用符がない場合、これは int、bigDecimal などの文字列以外の型であることを意味します。
  • サブタイトルや特殊記号を含む文字列を一重引用符で囲まないと、型変換が失敗し、SQL を実行できなくなります。

上の図に示すように:

1054 - 'where 句' に不明な列 '000w1993521' があります。時間: 0.008000 秒

まず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. 生成条件<br /> 演算子が異なる型のオペランドで使用される場合、オペランドの互換性を保つために型変換が行われます。暗黙的な変換は次の場合に発生します。

  1. 2 つのパラメータのうち少なくとも 1 つが NULL の場合、比較の結果も NULL になります。例外として、<=> を使用して 2 つの NULL を比較すると 1 が返されます。どちらの場合も、型変換は必要ありません。
  2. 両方のパラメータは文字列であり、型変換なしで文字列として比較されます。
  3. 両方のパラメータは整数なので、型変換なしで整数として比較されます。
  4. 16 進数値は、数値以外の値と比較するとバイナリ文字列として扱われます。
  5. 1つのパラメータがTIMESTAMPまたはDATETIMEで、もう1つのパラメータが定数の場合、定数はタイムスタンプに変換されます。
  6. 1 つのパラメータが 10 進数型の場合、他のパラメータが 10 進数または整数であれば、整数は比較のために 10 進数に変換されます。他のパラメータが浮動小数点数の場合、10 進数は比較のために浮動小数点数に変換されます。
  7. それ以外の場合は、比較の前に両方の引数が浮動小数点数に変換されます。

2. 実際に遭遇した状況を分析する

1. すると、上で述べた例は整数と文字列の比較であり、他のケースに属するものであることは明らかです。それではまずインデックス失敗の理由を分析してみましょう

  • 暗黙的な変換であるため、比較する値はすべて浮動小数点数に変換して比較する必要があります。
  • まずクエリ条件値を浮動小数点数に変換し、次にテーブルのレコード値を変換します。そのため、以前に作成されたインデックスソートは有効ではなくなります。暗黙的な変換 (関数) によって元の値が変更されているため、オプティマイザーはここでインデックスを使用せず、直接フル テーブル スキャンを使用します。

2. 上記のクエリ結果に示すように、一致しない値(または部分的に一致する値)をクエリします。実際にソース コードを確認する必要があります。これは MYsql の暗黙的な変換ルールです。ここでは詳細に分析しません(関連する文書が見つからなかったため)
歴史的な理由により、古い設計との互換性が必要です。明示的な変換を実行するには、MySQL の型変換関数 cast と convert を使用できます。
要約する

  • 暗黙的な変換や関数を使用すると、インデックスが失敗し、データが不正確になる可能性があります。
  • 暗黙的な変換条件とルール
  • 暗黙的な変換によってインデックスが失敗する具体的な理由は、比較値を異なる型に変換する必要があることです。
  • 暗黙的な型変換は避けてください。暗黙的な変換には、主に、一貫性のないフィールド型、in パラメータ内の複数の型、一貫性のない文字セット型または校正ルールなどが含まれます。

参照する
型変換
https://xiaomi-info.github.io/2019/12/24/mysql-暗黙的変換/
https://zhuanlan.zhihu.com/p/95170837

MySQL 5.6 の「暗黙の変換」によって発生するインデックスの無効化と不正確なデータに関するこの記事はこれで終わりです。MySQL 5.6 の暗黙の変換によって発生するインデックスの無効化の詳細については、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • MySQLの整数および文字列インデックスの無効化または暗黙的な変換に関する簡単な説明
  • MySQLの驚くべき暗黙の変換
  • MySQLの暗黙的な変換について話す
  • MySQLの暗黙的な変換問題の解決
  • MySQL インデックス無効化の暗黙的な変換の問題

<<:  Vueダイナミックフォームの詳細な応用

>>:  docker version es、milvus、minio 起動コマンドの詳細な説明

推薦する

Vue3.0 + TypeScript + Vite初体験の詳しい説明

目次プロジェクトの作成プロジェクト構造メイン.jsアプリ.vue:設定コンポジションAPI参照反応的...

Linux(中心OS7)は、Java Webプロジェクトの実行環境を構築するためにJDK、Tomcat、MySQLをインストールします。

1. JDKをインストールする1. 古いバージョンまたはシステム独自のJDKをアンインストールする...

Vue における LocalStorage と SessionStorage の違いと使い方

目次LocalStorageとはSessionStorageとはLocalStorage と Ses...

MySQL の日付と時刻関数の概要 (MySQL 5.X)

1. MySQLは現在の日付と時刻を取得する関数1.1 現在の日付 + 時刻 (日付 + 時刻) ...

IE で UTF8 エンコードされたページで行が理由もなく空白のままになり、UTF8 ページが表示されない問題の解決方法

理由は、すべてのファイルが utf8 でエンコードされているためです。ファイルがインクルードされると...

優れた登録プロセスの手順

ウェブサイトにとって、これは最も基本的な機能です。それでは、登録プロセスに含まれる手順を見てみましょ...

このリファレンスとJavaScriptのカスタムプロパティの詳細な説明

目次1. このキーワード2. カスタム属性3. 包括的なケース1:タブの実装付録要約する1. このキ...

最適なウェブページ幅とその互換性のある実装方法

1. Web ページをデザインするときに、幅を決定するのは非常に面倒な作業です。 jb51.net ...

Docker ビルド kubectl イメージ実装手順

プログラムサービスがgitlab ci/cdと統合されたk8sを使用してデプロイされている場合、gi...

Vueルーティングはページステータスを復元する操作メソッドを返します

ルートパラメータ、ルートナビゲーションガード: ページが戻ったときに検索結果を保持する需要シナリオ:...

MySQL バッチ挿入とユニークインデックスの問題に対する解決策

MySQL バッチ挿入の問題プロジェクトを開発しているときに、古いシステムの基本データを事前にインポ...

vue.js パッケージ化プロジェクトの後の空白ページの解決策

Vueに触れたばかりのパートナーの多くは、開発環境ではVueプロジェクトは正常であるが、パッケージ化...

HTML 選択ボックスのプレースホルダーの作成に関する問題

テキスト入力でプレースホルダーを使用していますが、問題なく動作します。しかし、選択ボックスにはプレー...

Mac に mysql5.7 をインストールするための完全な手順 (画像とテキスト付き)

最近、Mac システムを使用して、ローカル Web サーバー環境を構築する準備をしていました。 Ma...

HTML テーブルの空白セル補完を実装する方法

私が初めて Web 開発を独学で学んだ頃は、いわゆる DIV/CSS レイアウトはなく、テーブル レ...