みなさん、こんにちは。私の名前はシャオリンです。
昨日、インデックスの無効化に関する記事を投稿しました。インデックスの無効化にまだ触れていないのは誰ですか。
記事の最後に興味深い考えの質問を残しました:
この質問は、実際には、以前の記事「SQLステートメントによって引き起こされた思考」のコメント領域にある読者の友人からの質問からのものです。
多くの読者がコメント欄で自分の考えを表明し、多くの読者が私と個人的に答えを話しました。
それで、私は今夜この質問についてあなたに話すつもりです。
トピック1
質問1は非常に単純です。誰もが答えを分析できると思います。昨日共有したインデックス無効化の記事でも言及されていました。
**「タイトル1」**のデータベーステーブルは次のとおりです。idは主キーインデックス、nameはセカンダリインデックス、その他のフィールドは非インデックスフィールドです。
これらの4つのあいまい一致クエリステートメントでは、最初と2番目がインデックススキャンを実行し、すべてがセカンダリインデックス(index_name)をスキャンすることを選択します。2番目のクエリステートメントの実行プランの結果を投稿します。
3番目と4番目の項目はインデックスに失敗し、実行プランの結果はtype = ALLになります。これは、全表スキャンを表します。
トピック2
トピック2のデータベーステーブルの特別な機能は、フィールドが2つしかないことです。1つは主キーインデックスIDで、もう1つはセカンダリインデックス名です。
トピック2のデータテーブルの場合、1番目と2番目のファジークエリステートメントもインデックススキャンを実行できます。2番目のクエリステートメントの実行プランは次のとおりです。Extraでのインデックスの使用は、カバーインデックスが使用されていることを示しています。
3番目のクエリステートメントの実行プランを見てみましょう(4番目は同じ結果です)。
実行プランの結果から、key = index_name、つまりセカンダリインデックスが使用されていることがわかります。また、ExtraのUsing indexは、カバーリングインデックスが使用されていることを示しています。
どうしてこれなの?
まず、このテーブルのフィールドには「非インデックス」フィールドがないため、select *
と同等ですselect id,name
。**このクエリのデータはセカンダリインデックスのB +ツリーにあります。これは、セカンダリインデックスのB+ツリーには「インデックス値」+プライマリキー値」が含まれているため、カバーインデックスであるセカンダリインデックスのB+ツリーを確認することですべての結果を見つけることができます。
ただし、実行プランのタイプはですindex
。これは、セカンダリインデックスのB +ツリーを完全にスキャンすることによってデータがクエリされることを意味します。つまり、インデックスツリー全体がトラバースされます。
1番目と2番目のクエリステートメントの実行プランでは、typeはですrange
。これは、インデックス列が範囲内で検索されることを意味します。つまり、インデックスツリーの順序が使用され、クエリ比較によってデータ行がすばやく検索されます。
したがって、type=rangeのクエリ効率はtype=indexのクエリ効率よりも高くなります。
フルテーブル(クラスター化インデックス)ではなく、フルスキャンセカンダリインデックスツリーを選択するのはなぜですか?
セカンダリインデックスツリーにはレコードが少ないため、「インデックス列+主キー値」のみがあり、クラスター化インデックスはより多くのものを記録します。たとえば、クラスター化インデックスのリーフノードは主キー値とトランザクションIDを記録します。 、トランザクションとMVCCのバックフローポインタ、および残りのすべての列。
さらに、このselect *は、テーブルの戻り操作を実行する必要はありません。
したがって、MySQLオプティマイザは、セカンダリインデックスツリーを直接トラバースするコストは、クラスタ化されたインデックスツリーをトラバースするよりもはるかに少ないと考えているため、MySQLは「フルスキャンセカンダリインデックスツリー」方式を選択してデータをクエリします。
このデータテーブルがインデックス付けされていないフィールドを追加するのはなぜですか。同じクエリステートメントを実行した後、どのようにして全表スキャンになることができますか?
他のフィールドを追加した後、select * from t_user where name like "%xx";
クエリ対象のデータはセカンダリインデックスツリーでのみ見つけることができず、クエリ作業を完了するためにテーブルの戻り操作が必要になります。さらに、左あいまいマッチングではインデックスツリーの順序を利用できません。データをすばやく見つけるには、セカンダリインデックスツリーを1つずつトラバースし、プライマリキーの値を取得してから、クラスター化されたインデックスツリーの対応するデータ行を取得する必要があります。
したがって、オプティマイザは、上記のクエリプロセスのコストが高すぎると判断し、データをクエリするために全表スキャン方式を直接選択します。
この質問から、左あいまい一致( "%xx"など)を使用しても、必ずしも全表スキャンにつながるとは限らないことがわかります。重要なのは、データテーブルのフィールドを確認することです。
データベーステーブルのフィールドに主キーとセカンダリインデックスしかない場合、左側のあいまい一致を使用しても、全表スキャン(type = all)は実行されませんが、全表スキャンのセカンダリインデックスツリー(type =インデックス)が実行されます。
もう1つの類似点は、ジョイントインデックスがインデックスに移動するために左端の一致に従う必要があることは誰もが知っていますが、データベーステーブルのフィールドがすべてインデックスである場合、クエリプロセス中に左端の一致の原則に従わなくても、インデックススキャンが実行され、タイプは次の図のようにインデックスでもあります。
それだけです、また会いましょう