MySQLクエリのパフォーマンスを最適化する前に、まずMySQLインデックス理論を習得する必要があります

データベースのインデックス作成は日常業務に必要です。インデックスの作成方法とインデックスの使用方法により、データクエリの効率を向上させることができます。また、インタビュープロセスでは、データベースのインデックスは、次のような質問が必要な知識ポイントでもあります。

インデックスの基礎となる構造を選択してから、なぜB +ツリーを選択するのですか?
さまざまなストレージエンジンのインデックスの兆候は何ですか?
インデックスタイプ
複合インデックスの保存方法
クエリ方法
左端のプレフィックスマッチングの原則

カバーリングインデックスとは何ですか?
これらを見て、どれだけ言って理解できますか?したがって、その内部原理を探求する必要があります。

インデックスとは何ですか?
インデックス作成の目的は、データの取得を高速化するように設計された一種の分散ストレージ(インデックスは非常に大きく、ハードディスクレベルに属するため、分散ストレージです)のデータ構造です。その原則は、時間とスペースを交換することです。
高速検索の本質はデータ構造です。さまざまなデータ構造を選択することで、さまざまなデータの高速検索が実現されます。インデックスには、ハッシュインデックスとB +ツリーインデックスが含まれます。

インデックスの基礎となる構造を選択してから、なぜB +ツリーを選択するのですか?
最終的な分析では、データベースインデックスの基本的な選択は検索効率を向上させることであるため、いくつかの問題を考慮する必要があります。

アルゴリズムの時間計算量
何か種類ありますか?
ディスクIOと
先読み注:ディスクIOは非常にコストのかかる操作であることを考慮して、コンピューターのオペレーティングシステムはいくつかの最適化を行いました。IOの場合、現在のディスクアドレスデータだけでなく、隣接する部分的な先読みの原理により、コンピュータがアドレスのデータにアクセスすると、隣接するデータにもすばやくアクセスされるため、データはメモリバッファにも読み込まれます。各IOによって読み取られるデータはページと呼ばれます。
ハッシュテーブル(ハッシュテーブル、ハッシュテーブル)
ハッシュテーブルは、キー(Key)に基づいてメモリの保存場所に直接アクセスするデータ構造です。

ここに写真の説明を挿入
キー値に基づいて関数を計算することにより、クエリ対象のデータがテーブル内の場所にマップされ、レコードにアクセスできるため、検索が高速化されます。クエリの時間計算量はO(1)ですが、衝突の問題があり、最悪の場合、時間計算量が急激に増加します。

また、ハッシュテーブルは正確なキー(等しい)検索にのみ適しており、範囲検索には適していません。範囲検索では、すべてのデータを一度に検索してメモリにロードする必要があります。これは非効率的であるため、基になるデータ構造には適していません。 Mysqlのインデックス。

「2020年の最新のJavaの基本と詳細なビデオチュートリアルおよび学習ルート!

通常の二分探索木
効率的な二分探索木を最適化するために、時間計算量が小さい場合
ここに写真の説明を挿入
、二分探索木の時間計算量はO(lgn)です。データがソートされるため、範囲探索は効率的です。

ただし、問題が発生します。左右の子ノードの深さが大きく異なる場合があります。最も極端なケースは、左側のサブツリーまたは右側のサブツリーのみです。現時点では、検索効率はO(n)であり、検索はO(n)です。パフォーマンスが急激に低下するため、Mysqlには適していません。基になるインデックスのデータ構造。
ここに写真の説明を挿入
平衡二分木(AVL木)二分木の
左右のサブツリーの深さが大きすぎるという問題を最適化するために、平衡二分木、つまり左右の子ノード間の深さの差を導入しました。 1を超えない。
平衡二分木が適切であると思われ、達成できる。

範囲検索とデータソートを実現できます。
優れたクエリパフォーマンスO(logn)
ここに写真の説明を挿入
注:上の図のディスクブロックはハードディスク上の保存場所を表しています
が、考慮すべき最も重要な要素の1つであるディスクIOと先読みとデータベースクエリデータのボトルネックはディスクIOにあります。バランスの取れたバイナリツリーを使用してインデックスに基づいて検索する場合、ディスクブロックが読み取られるたびにIOが実行されます。これは、コンピューターの先読みを実現しません。 、結果として検索効率が向上します。インデックスとしてのバランスの取れたバイナリツリーの問題を要約します(上の図)。ディスクブロックはハードディスク上の保存場所を表します)。

深すぎます(つまり、パスが2つしかない)。深さが深いほど、実行されるIO操作が多くなります。
小さすぎます。すべてのIOはディスクブロックデータのみをクエリするため、IOが無駄になりすぎます。オペレーティングシステムでは、1つのIOに最低4K、Mysqlに16Kが規定されており、図のディスクブロックは明らかに4Kに到達できません
。B+ツリー
ディスクIOと先読みを最適化し、IO操作を減らすには、数が少なすぎます。パスを複数のRoadに置き換えると、BツリーとB +ツリーの使用を検討できますが、Bツリーの各ノードは最大2つのキーの格納に制限されているため、IO操作が頻繁に発生します。最適化のアイデアは次のとおりです。1つのディスクIOメモリで可能な限り多くのデータを読み取ると、B +ツリーも表示されます。

B +ツリーのノードは多くのインデックスを格納でき、B +ツリーのリーフノードのみがデータを格納します
。隣接するノード間には、先行ノードと後続ノードの関係がいくつかあります
リーフノードは順番に配置されます
ここに写真の説明を挿入
。Bツリーと比較して、利点B +ツリーの内容は次のとおりです。

B +ツリースキャンデータベースは、テーブルをスキャンする能力が高く、
Bツリーデータは各ノードに格納され、ノードの物理アドレスはランダムであるため、テーブルをスキャンする場合
、B +ツリーのデータはランダムIOに格納されます。リーフノードの場合、リーフノードのデータは連続しているため、テーブルをスキャンするときのIOの相対的な順序

B +ツリーのディスクの読み取りおよび書き込み機能はより強力であり、ブランチノードはデータを格納しませんが、より多くのキーワードを格納します。一つのIOは、複数のキーワードを読むことができます。
B +ツリーは強いソート能力を持っているB +ツリーのリーフノードに格納されたデータがすでにソートされています。。
の実施形態
指数は、異なるストレージエンジンでも同じである一般的なものは次のとおりです。

InnoDBエンジンは、クラスタ化インデックス法(インデックス及びデータが同一のファイルに格納されている)に反映される
のMyISAMエンジンは、非クラスタ化インデックス法に反映される(インデックスとデータは2つのファイルに格納されている)
クラスタ化インデックス法(InnoDBストレージエンジン)
でInnoDBストレージエンジンでは、インデックスとデータは同じファイルに保存されます。これはクラスター化インデックスです。また、InnoDBは主キーIDインデックスツリーを自動的に作成するため、テーブルの作成時に主キーを指定する必要がある理由。

その中で、主キーインデックス(クラスター化インデックス)のリーフノードは、データの物理アドレスではなく、データを記録します。補助インデックスのリーフノードには、主キーキーが格納されます。したがって、補助インデックスを使用してデータを検索する場合は、実際にインデックスを2回チェックします(補助インデックスと主キーインデックス)。

最初にセカンダリインデックスツリーにクエリを実行してプライマリキーを見つけ、
次にプライマリキーインデックスツリーのプライマリキーに基づいてデータをクエリします。
ここに写真の説明を挿入
非クラスター化インデックス方式(Myisamストレージエンジン)
Myisamストレージエンジンでは、インデックスとデータが保存されます。 2つのファイルにあり、非クラスター化インデックスに属しています。主キーインデックスであるか補助インデックスであるかに関係なく、そのリーフノードはデータが記録される物理アドレスです。

ここに写真の説明を挿入
MySQLインデックスタイプ
MySQLインデックスは次のように分類できます。

通常のインデックス(インデックス):高速検索
一意のインデックス:
主キーインデックス:主キー:高速検索+制約(空ではなく一意)
一意のインデックス:一意:高速検索+制約(一意)

ジョイントインデックス:
主キー(id、name):ジョイントプライマリキーインデックス
unique(id、name):ジョイント一意インデックス
インデックス(id、name):ジョイント通常インデックス

全文索引全文:長い記事を検索する場合に最適です。
その中で、主にジョイントインデックス、ストレージ構造、およびクエリメソッドの問題を理解します。

ジョイントインデックス
複数の列で構成されるインデックスであるジョイントインデックスはジョイントインデックスと呼ばれ、単一列のインデックスは特別なジョイントインデックスです。ストレージ構造は次のとおりです。

ジョイントインデックスの場合、そのストレージ構造は単一値インデックスよりもわずか数列多いだけです。結合インデックスの列データはインデックスツリーに記録され(結合インデックスが異なる、B +ツリーも異なります)、ストレージエンジン最初に1つのインデックス列が並べ替えられた後、他の列は同じ値で順番に並べ替えられます。ここに写真の説明を挿入

注:リーフノードの最初の行は順番に並べ替えられ、2番目の列は最初の列に基づいて並べ替えられ、最初の列は等しく、次の列は並べ替えられます。
共同インデックスクエリモードでは、ストレージエンジンは最初にルートノード(通常はメモリに常駐)から検索し、次にインデックスの下のデータ要素(ID値)が見つかるまで他の列でクエリを実行します。最終データは、主キーインデックスツリーから検索されます。

そして、共同インデックス選択の原則:

左端のプレフィックス一致の原則(最初に頻繁に使用される列)は
、分散列の優先度高く、
幅の小さい列が最初です。
左端のプレフィックス一致の原則
は、インデックスの構築方法とジョイントインデックスの格納構造に関連しています。上記の理解と分析に基づいて、ジョイントインデックスは、次のように、複数列のインデックスの最初の列からインデックスを検索した場合にのみ有効になると結論付けることができます。

テーブルuserにジョイントインデックス(a、b、c)があるとすると、ストレージエンジンが最初のフィールドでソートするジョイントインデックスであるため、b = 1およびc = 2がインデックスにヒットしないユーザーから*を選択します。 。次に、2番目のフィールドで順番に並べ替えます。
分散
インデックス内の列の分散が低すぎる場合、オプティマイザはインデックスを直接使用しない場合があります。分散の計算方法:

=データ列の総分散量がデータ量/列と重ならない

カバーインデックスインデックス
にクエリが必要なすべてのフィールドの値が含まれている(またはカバーしている)場合、それはカバーインデックスと呼ばれます。つまり、クエリのためにテーブルに戻らずにインデックスのみがスキャンされます。インデックスをカバーすると、データベースIOを削減し、ランダムIOをシーケンシャルIOに変更し、クエリのパフォーマンスを向上させることができます。

InnoDB補助インデックスの場合、行の主キー値はリーフノードに格納されるため、補助インデックス(ジョイントインデックスを含む)がクエリをカバーできる場合は、主キーインデックスの二次クエリを回避できます。といった:


共同インデックスを作成しますcreate index name_phone_idx on user(name、phoneNum); –
現時点ではカバーインデックスです。理由は、名前に従ってチェックし、インデックスname_phone_idxを
押すためです。–キーはname、phoneNum、すでにクエリ列が含まれています。
select name、phoneNum where name = "Zhang San";
-idが主キーの場合、この時点ではカバーインデックスとも呼ばれます。理由:セカンダリインデックスのリーフノードにプライマリキーが
格納されますselect id、name、phoneNumここで、name = "Zhang San"; MySQLインデックスの
要約に
は、習得する必要のある多くの知識があります。インデックスの基礎となるストレージ構造、さまざまなストレージエンジンでのインデックスの明示、およびインデックスタイプの基本的な知識分析を学びました。その後のデータベース最適化のための理論的知識サポートを提供します。、最適化計画をよりよく理解します。

リンクアドレス:https://segmentfault.com/a/1190000038346710

おすすめ

転載: blog.csdn.net/weixin_46699878/article/details/110641417