技術共有

MySQL インデックス アプリケーション

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

目次

インデックスアプリケーション

MySQL にはどのようなインデックスがありますか?

通常のインデックスとユニークなインデックスの違いは何ですか? どちらの方が更新パフォーマンスが優れていますか?

クラスター化インデックスの主キー インデックスを設定する方法 質問: 設定しないとどうなりますか?

インデックスを構築するために通常どのようなフィールドを選択しますか?

インデックスは多ければ多いほど良いのでしょうか?

インデックスを最適化する方法 (インデックスの最適化、インデックスの失敗の防止、主キーの増分、プレフィックス インデックスの最適化)

インデックスが作成された場合、それはクエリ時に使用されますか? (インデックスが失敗した場合、オプティマイザーはコストに基づいて実行プランを選択します)

varchar 型の日付フィールドを定義し、データの 1 つが「20230922」で、この日付フィールドにインデックスがある場合、クエリの where 条件が一重引用符なしの where time=20230922 である場合、インデックスがまだヒットするのはなぜですか?

MySQL の最新バージョンでは、インデックス障害のケースは解決されましたか? (関数インデックス: 関数によって計算された値にもインデックスを付けることができます、インデックス ジャンプ スキャン メカニズム (左端のプレフィックス))

一番左の一致原理は何ですか?

結合インデックスを作成する際に注意すべき点は何ですか? (最も区別されたものを左端に配置する、左端の一致原則、範囲クエリの後にインデックスを使用しない)

左端の一致原則クエリ順序

インデックスのプッシュダウンとは何ですか? データクエリを最適化するために MySQL5.6 で追加されました

a>1、b=2、c<3のインデックスを作成するにはどうすればよいですか?

(A,B,C) 結合インデックス select * from tbn where a=? and b in (?,?) and c>?

a>100、b=100、c=123 が d 順に並べられる結合インデックスを作成するにはどうすればよいですか?

ID、名前を XX から選択 (年齢 > 10)、名前は「xx%」のようなものです。結合インデックス (名前、年齢) があります。クエリ プロセスについて話しましょう。


インデックスアプリケーション

マイグレーションどのようなインデックスがありますか?

MySQL には主キーインデックス、ユニークインデックス、通常インデックス、プレフィックスインデックス、ユニオンインデックスこういったタイプのインデックスです。

Innodb エンジンでは、すべてのデータベース テーブルに主キー索引インデックス列の値は許可されませんNULL値たとえば、テーブルの id フィールドは主キー インデックスです。

一意のインデックス: データ列内のデータの各行の一意性を確保しますが、NULL 値は許可されます。

それから頻繁にクエリされるフィールドについては、このフィールドに対して通常のインデックスを作成できます。複数のフィールドがある場合は、作成することを検討できます。ユニオンインデックス、使用インデックスカバレッジ機能によりクエリの効率が向上します。

長いテキスト、文字列、および記事タイトル、製品名などの他のタイプのフィールドの場合、これらのフィールドのプレフィックス部分のみインデックスを付けることができます。プレフィックスインデックスを作成して、インデックスの記憶領域を削減します。

通常のインデックスと一意のインデックスの違いは何ですか? どちらの方が更新パフォーマンスが優れていますか?

  • 一意のインデックスは、最初の一致を見つけた後に検索を終了できるため、単一の値をクエリする場合に若干高速になる可能性があります。

  • 挿入および更新操作の場合、一意性チェックを必要としないため、通常のインデックスの方が若干高速になる可能性があります。

  1. 通常のインデックス列の値は繰り返すことができますが、一意のインデックス列の値は一意である必要があります。重複する値を一意のインデックスに挿入すると、一意性の制約によりエラーが報告されます。

  2. 私は思う通常のインデックスの更新パフォーマンスが向上します。これは、通常のインデックスが更新されるときに、更新されたデータ ページが更新されないためです。メモリその場合は、更新操作を変更バッファーに直接キャッシュすることができ、更新操作は完了します。 (一意性チェックは必要ありません)

  3. しかし、更新されたデータ ページがメモリその場合は、対応するデータ ページをディスクからメモリに読み取って、競合があるかどうかを判断する必要があります。これには、ディスクのランダム化が必要になります。IOアクセス。

  4. 通常のインデックスは変更バッファ機能を使用できるため、通常のインデックスの更新は一意のインデックスよりも高速です。ランダムなディスクアクセスが減少するため、アップデートのパフォーマンスが向上します。

クラスター化インデックス主キーインデックスを設定するにはどうすればよいですか? 質問: インデックスを設定しないとどうなりますか?

InnoDB はクラスター化インデックスを作成するときに、さまざまなシナリオに従ってさまざまな列をインデックスとして選択します。

  1. 主キーがある場合は、デフォルトで主キーがクラスター化インデックスのインデックス キーとして使用されます。

  2. 主キーがない場合は選択します。最初のものには含まれていません NULL値の唯一の列は次のとおりですクラスター化インデックスインデックスキー

  3. 上記のいずれかが存在しない場合、InnoDB はクラスター化インデックスのインデックス キーとして暗黙的な自動インクリメント ROWID 列を自動的に生成します。

インデックスを構築するために通常どのようなフィールドを選択しますか?

インデックス作成が適用されるシナリオ:

  1. フィールドには一意性の制限がありますプロダクトコードなど

  2. WHERE クエリ条件で頻繁に使用されるフィールドこれにより、テーブル全体のクエリ速度が向上します。クエリ条件がフィールドでない場合は、結合インデックスを確立できます。

  3. GROUPBY と ORDER BY でよく使用されるフィールドB+ ツリー内のレコードはすべてインデックスの確立後にソートされるため、検索時に再度ソートする必要はありません。

インデックス作成に適さないシナリオ

  1. WHERE 条件、GROUP BY、ORDER BY で使用されないフィールドフィールドを配置できない場合、インデックスは物理スペースを占有するため、通常はインデックスを作成する必要はありません。

  2. 目立たない分野インデックスを作成する必要はありません。たとえば、性別フィールドに男性と女性のみが含まれている場合、男性と女性のレコードがデータベース テーブルに均等に分散されている場合、どの値が検索されても、データの半分が検索される可能性があります。得られる。このような場合は、インデックスを作成しない方がよいでしょう。 マイグレーションまだ1つありますクエリオプティマイザークエリ オプティマイザーは、特定の値がテーブル内のデータ行の高い割合で出現することを検出すると、通常、インデックスを無視して実行します。フルテーブルスキャン

  3. 頻繁に更新されるフィールドたとえば、インデックス フィールドは頻繁に変更されるため、電子商取引プロジェクトのユーザー残高のインデックスを作成しないでください。維持する B+ツリー順序性を維持するには、頻繁にインデックスを再構築する必要があり、このプロセスはデータベースのパフォーマンスに影響します。

  4. 順序なしの値を使用することはお勧めしません(ID カード、UUID など) をインデックスとして使用する場合、主キーが不確実な場合、リーフ ノードの頻繁な分割やディスク ストレージの断片化が発生します。

  • データ テーブルは小さくなります。テーブル内のデータの量が少ない場合、またはクエリでテーブル内のデータの大部分をスキャンする必要がある場合、データベース オプティマイザはインデックスを使用する代わりにテーブル全体のスキャンを選択することがあります。この場合、インデックスを維持するコストがパフォーマンスの向上よりも高くなる可能性があります。

インデックスは多ければ多いほど良いのでしょうか?

いいえ、インデックスによってクエリの効率は向上しますが、インデックスを 1 つ作成すると、新しい B+ ツリー インデックスが生成されることになり、特にテーブル データの量が非常に多い場合、インデックスが占有するスペースが増加します。

インデックスの数が増えると、データベースの書き込みパフォーマンスが低下します。これは、テーブルを追加、削除、または変更するたびに、各 B+ ツリー インデックスの順序を維持する必要があるためです。

インデックスを最適化するには? (カバーインデックスインデックスの失敗を最適化して防止します。主キー増分、プレフィックス インデックスの最適化)

これらの最適化方法を使用しました

  1. 複数のフィールドのデータをクエリする必要がある SQL の場合、次のように作成できます。ユニオンインデックス, したがって、クエリメソッドは次のようになりますカバーインデックス、テーブルバッキングを回避し、多数の I/O 操作を削減します。

  2. 私たちの主キーインデックスの値は増加することが好ましいインデックスはデータを順番に格納するため、主キーの値がランダムな値である場合、ページ分割が発生する可能性があります。ページ分割により大量のメモリ フラグメントが発生し、インデックス構造がコンパクトになりません。クエリの効率に影響します。

  3. 私たちが欲しいのはインデックスの書き込み失敗を回避する 構文 インデックス列に対して左または左のあいまい一致を実行しないなどのステートメントでは、インデックスに対して計算、関数、および型変換操作を実行しません。結合インデックスを正しく使用するには、左端の一致原則に従う必要があります。WHERE 句で、OR の前の条件列がインデックス列であり、OR の後の条件列がインデックス列ではない場合、インデックスは失敗します。

  • 等しくない (<>) または NOT 演算子: これらの演算子はテーブル全体をスキャンするため、通常、インデックスを無効にします。

  • OR 演算子: クエリ条件で OR が使用されており、OR の両側の条件に異なるインデックスが含まれる場合、これらのインデックスは使用できない場合があります。

    • 使用 OR 演算子 (場合)OR 両側の条件には異なるインデックスが含まれており、ほとんどの場合、データベース エンジンはクエリを最適化するために複数のインデックスを同時に使用できません。これはなぜなら OR 演算子はどちらかの条件を満たすだけでよいため、クエリの最適化が複雑になります。

  1. 大きな文字列にインデックスを付ける場合の使用を検討できます。プレフィックスインデックスインデックスの格納領域を節約し、クエリのパフォーマンスを向上させるために、インデックス列のプレフィックス部分のみにインデックスが付けられます。

  2. インデックスは NOT に設定するのが最適です ヌル注:インデックスをより有効に活用するには、インデックス列を NOT NULL 制約に設定する必要があります。理由は 2 つあります。

    1. インデックス列に NULL が存在すると、オプティマイザのインデックス選択がより複雑になり、カウントなどの操作の最適化がより困難になります。

    2. NULL 値は意味のない値ですが、物理的な領域を占有します。NULL 値の列が存在します。NULL を格納するには少なくとも 1 バイトのスペースが使用されます 値のリスト

インデックスが作成された場合、クエリ時にそのインデックスが使用されますか?オプティマイザコストに基づいて実行計画を選択)

いいえ。

  1. 私は学んだクエリでインデックスが使用されている場合でも、インデックスが使用されない場合があります。

    1. たとえば、クエリ ステートメントがインデックス フィールドに対して左あいまい一致、式の計算、関数、および暗黙的な型変換操作を実行する場合、クエリ ステートメントはインデックスを通過できず、クエリ メソッドはフル テーブル スキャンになります。

    2. そして私たちは使用しますユニオンインデックスクエリを実行するときに、左端の一致原則に従わない場合も、インデックスの失敗が発生します。

  2. オプティマイザーは、コストを考慮してクエリ方法を選択するクエリにセカンダリ インデックスを使用する場合、オプティマイザはテーブルの戻りのコストとテーブル全体のスキャンのコストを計算します。テーブルの戻りのコストが高すぎる場合、オプティマイザはインデックスを使用せず、フルテーブルスキャン。

varchar 型の日付フィールドを定義し、データの 1 つが「20230922」で、この日付フィールドにインデックスがある場合、クエリの where 条件が一重引用符なしの where time=20230922 である場合、インデックスがまだヒットするのはなぜですか?

インデックスにヒットしません。

mysql が遭遇しているため文字列と数値の比較いつ起こるか暗黙的な型変換、 意思文字列オブジェクトを数値に変換する、この変換プロセスには実際に以下のことが含まれます。関数 。ご指摘のクエリでは、日付フィールドが文字列であるため、暗黙的な型変換が発生すると、日付インデックス フィールドに適用され、インデックスに対して関数計算が実行されると、インデックスは無効になります。

整数型のインデックス列の場合、たとえばid関数の計算を行わずに、値がインデックスに直接格納される列。これはクエリで使用することを意味しますidマッチングする場合は必要ありませんid関数計算や変換を実行し、単純に整数値を比較します。

マイグレーション最新バージョンでは、インデックスの失敗のケースは解決されましたか?関数計算後の値にもインデックスを付けることができ、インデックス スキップ スキャン メカニズム (左端のプレフィックス))

MySQL8.0でフィールドを追加できることを知りました関数インデックス、この新機能により、インデックスで関数を使用するときにインデックスが失敗する問題を解決できます。

もう一つの新機能は、インデックススキップスキャン, バージョン 5.7 より前では、ジョイント インデックスを使用する場合、左端の一致原則が満たされていない場合、インデックスの失敗が発生します。ただし、8.0 でインデックス スキップ スキャン機能が導入された後は、左端の一致原則が満たされていてもジョイント インデックスを使用できます。はフォローされていません。

一番左の一致原理は何ですか?

(a, b, c) 結合インデックスがあるとします。その格納順序は、最初に a でソートされ、次に a が同じ場合は b でソートされ、次に b が同じ場合は c でソートされます。この機能により、ジョイント インデックスを使用する場合は、左端の一致の原則が適用されます。具体的なルールは次のとおりです。

  1. MySQL のフェデレーテッド インデックスは次から始まります。左端のインデックス列がクエリ条件と一致し始め、その後、左から右の順序で一致します。クエリ条件で列が使用されていない場合、その列の右側にあるすべての列にインデックスを付けることはできません。

  2. クエリ条件にカラムを使用する場合、ただし、この列の値には範囲クエリが含まれており、範囲クエリのフィールドを使用できます。ユニオンインデックスただし、結合インデックスは範囲クエリ フィールドの後ろのフィールドでは使用できません。

したがって、結合インデックスを使用する場合は、左端の一致原則に従う必要があります。そうしないと、一部のインデックス フィールドにインデックスが付けられない可能性があります。

確立するユニオンインデックス注意する必要はありますか? (最も区別されたものは左端に配置され、左端の一致原則、範囲クエリの後にインデックスは使用されません)

  1. ほとんどより区別性の高いフィールドを配置しますユニオンインデックス左端、 役立つインデックスフィルタリング効果の向上、UUID などのフィールドは、結合インデックス列の先頭にインデックスを作成したりランク付けしたりするのに適しています。

  2. 識別性の低いフィールドが結合インデックスの左端に配置されている場合、クエリ オプティマイザーがインデックスを使用する代わりにテーブル全体のスキャンを選択する可能性があります。

  3. ジョイントインデックスの左端のマッチング原則は、範囲クエリ (&gt;、&lt; など) が発生すると、マッチングが停止します。つまり、範囲クエリのフィールドはジョイント インデックスを使用できますが、範囲クエリ フィールドの背後にあるフィールドはジョイント インデックスを使用できません。ただし、&gt;=、&lt;=、BETWEEN などの 4 つの範囲クエリについては、前方一致一致と同様に一致は停止しません。

    1. MySQL では、BETWEEN には、&gt;= および =&lt; と同様に、value1 と value2 の境界値が含まれます。

    2. 参考リンク https://zhuanlan.zhihu.com/p/573138586

左端の一致原則クエリ順序

 

select * from T where c=1 and a=2 and b=3;

abc にはインデックスを付けることができます。 クエリ条件フィールドの順序は影響しません、MySQL オプティマイザーはフィールドのクエリ順序の調整に役立つため、左端の一致原則にも準拠します。

インデックスの下押すそれは何ですか? データクエリを最適化するために MySQL5.6 で追加されました

インデックスのプッシュダウンを軽減できるセカンダリインデックスクエリ中にテーブルを返す操作により、クエリの効率が向上します。 サーバー層は、ストレージ エンジン層によって処理される処理の一部を担当します。それに対処しに行きました。

  • インデックス条件を使用せずにプッシュダウン最適化を行う場合、ストレージ エンジンはインデックスを通じてデータを取得し、それを MySQL Server に返します。MySQL サーバー フィルター条件を判断します。

  • インデックス条件プッシュダウン最適化を使用する場合、インデックス付きカラムに特定の判定条件がある場合、MySQL Server は判定条件のこの部分をストレージ エンジンにプッシュダウンし、ストレージ エンジンはインデックスが渡された条件を満たしているかどうかを判定します。 MySQL サーバー。インデックスが条件を満たした場合にのみ、データが取得され、MySQL サーバーに返されます。

インデックス条件プッシュダウンの最適化により、ストレージ エンジンが基になるテーブルをクエリする回数が減り、 マイグレーション サーバーがストレージ エンジンからデータを受信した回数。

 

select * from t_user where age > 20 and reward = 100000;

a&gt;1、b=2、c&lt;3のインデックスを作成するにはどうすればよいですか?

  1. (abc)、(acb)、(ab)、(ac) ジョイント インデックスを作成します。インデックスのみ作成できます。

  2. (cab)、(cba)、(ca)、(cb) ジョイント インデックスを作成します。インデックス付けできるのは c だけです

  3. (ba) ジョイント インデックスを作成します。b と a の両方にインデックスを付けることができます

  4. (bc) ジョイント インデックスを作成します。b と c の両方にインデックスを付けることができます

  5. 作成(バック) ユニオンインデックス、b および a は両方ともインデックスを作成できますが、() よりも遅くなります。) ジョイント インデックスにはもう 1 つの利点があります。c フィールドは次のことができます。インデックスのプッシュダウン、テーブルの戻り数が減ります。

  6. 作成する(bca) ユニオンインデックス、b と c の両方にインデックスを付けることができますが、(bc) ジョイント インデックスよりも 1 つ利点があり、a フィールドはインデックスのプッシュダウン、テーブルの戻り数が減ります。

(A、B、C) ジョイントインデックス select * from tbn where a=? and b in (?,?) and c>? インデックスされるのでしょうか?

このクエリではジョイント インデックスが使用されます。 (A,B,C)、条件はインデックス列に基づいているため、 ABC 注文が来る、これが理想的な使用シナリオです。

  1. のために A=?: この条件は完全一致です。MySQL はインデックスを使用して、条件を満たす条件を見つけます。 A=? の記録。

  2. のために B IN (?, ?): この条件は次のことを指定します B 列は 2 つの可能な値を取ることができます。 MySQL はインデックスを使用して一致するものをすべて検索しますA=? そしてB 列は、これら 2 つの値のいずれかを持つレコードです。

  3. のために C>? : この条件は範囲クエリです。すでに基づいていますA そしてB フィルタに基づいて、MySQL はインデックスを使用して検索を続けます。C 指定された値より大きい列値を持つレコード。

ここで、a&gt;100、b=100、c=123 を d で並べ替えます。ユニオンインデックス?

私は思う確立する bcda 順番にユニオンインデックスより良い、この時点では、b フィールドと c フィールドの両方にインデックスを付けることができます。d インデックスの順序付けを使用して、ファイルの並べ替え (余分な並べ替え) を回避できます。、最後の a フィールドにインデックスを付けることはできませんが (a の順序が間違っています)、インデックスを使用してプッシュダウンしてテーブルの戻り数を減らすことができます。

年齢が10以上で名前が'xx%'のようなXXからID、名前を選択、ユニオンインデックス(名前、年齢)、クエリのプロセスについて話してください

構造的には、ジョイント インデックスの順序は名前、次に年齢です。名前が等しい場合は、最初に名前で並べ替えられ、次に年齢で並べ替えられます。したがって、オプティマイザは、この時点では name が正しいファジー クエリであるため、最初に name と一致する必要があり、インデックスの失敗は発生しないため、この SQL は結合インデックスを使用できます。

具体的には、名前のみをインデックスできるためです。名前右ファジークエリの後、年齢フィールドの値は順序が整っていないため、年齢のインデックスは作成できませんが、年齢のインデックスは作成できます。インデックスのプッシュダウン

最後にクエリされるフィールドは id と name です。これら 2 つのフィールドはジョイント インデックスで見つかるため、テーブルを返す必要はありません。これはインデックス カバレッジ クエリです。

名前右ファジー クエリは範囲クエリであり、次のフィールドにはインデックスを作成できません