MySQLパフォーマンスの最適化-インデックス作成の基本原則

このチュートリアルは私の学習ノートです。エラーが発生した場合は修正してください。

1.索引の紹介

1.インデックスの役割

MySQLインデックスの確立は、MySQLの効率的な操作にとって非常に重要です。インデックスが作成された後、データベースは全テーブルクエリを実行しませんが、ディレクトリ検索と同様の方法を使用して直接クエリを実行し、関連するデータを探します。インデックスは、 MySQLの検索速度を改善するために、より一般的に使用されるものは、主キーインデックス、一意のインデックス、通常のインデックスなどです。

本質:インデックスは、MySQLが効率的にデータを取得するのに役立つソートされたデータ構造です。

2.インデックスを作成する方法

#表结构存在时创建索引
CREATE INDEX indexName ON mytable(username(length)); 
#或 
ALTER table tableName ADD INDEX indexName(columnName)
#建表时创建索引
CREATE TABLE mytable(  
		ID INT NOT NULL,   
		username VARCHAR(16) NOT NULL,  
		INDEX [indexName] (username(length))  
);  
#删除索引
DROP INDEX [indexName] ON mytable; 

2.一般的に使用されるツリー構造の紹介

MySQLインデックスはB + Treeを使用しています。各属性構造の長所と短所を分析しましょう。

1.二分探索木

ツリー構造の各親ノードには最大で2つの子ノードがあります。データを挿入すると、データは親ノードと比較されます。データが大きい場合は右側に挿入され、小さい場合は左側に挿入され
二分木挿入
ます。検索中は、親ノードのみを比較する必要があります。子ノードをすばやく見つける:
二分木検索
図に示すように、インデックスが使用されていない場合、データベースは全テーブル検索を実行します。ノード9を見つけるには、バイナリツリーをインデックスとして使用しながら、最大7回の検索を実行する必要がある場合があります。見つけてください。

しかし、mysqlはインデックスメソッドとしてバイナリツリーを使用していません。バイナリツリー構造の偶発的な状況を見てみましょう。
二分木の特別な場合
データが常に増加/減少している場合、バイナリツリーを使用すると、子ノードのデータは常にクエリの親ノードの右側/左側に追加されますいつでも、まだ全表スキャンがあります!

2.赤黒木

赤黒木の基本原理は二分木と同じですが、赤黒木が二分木と比較され、自動バランスアルゴリズムが追加されます。ツリー構造の両側のノードが不均衡である場合、ツリー構造は自動的に再編成され、両側のバランスが確保されます。ツリーは一種の「バイナリバランスツリー」です(実際のバイナリバランスツリーと比較して、赤黒ツリーはすべてのノードのバランスを保証せず、ツリー構造の過度の再編成とリソースの浪費を回避します)。

今すぐ状況を見てみましょう:
赤黒木
赤黒木の自動バランスアルゴリズムがバイナリツリーの欠陥を補いますが、mysqlは図の例のようにmysqlインデックス構造として赤黒ツリーをまだ使用していませんが、自動バランスアルゴリズムがありますが、データベースにはまだ必要です子ノードの場所を特定するためにディスクが非常に頻繁に読み取られ、システムがディスクと直接対話するのは非常に遅いプロセスなので、mysqlは赤黒木をインデックス構造として使用しません。

3. Bツリー

Bツリー
はディスクからコンテンツを頻繁に読み取るのが非常に遅いため、複数のデータをノードとして直接保存します。ノードの子ノードも複数のデータを保存します。ディスクからノードを読み取る場合は、複数のデータを直接結合します。そして、読んで比較してください。
Bナンバー構造
Bツリーの誕生は、主にシステムとディスクの間の相互作用の数を減らすことです。特定の量のデータを1回の比較のためにメモリに直接読み取ることができます。MySQLは、インデックスストレージにBツリーのバリアントであるB +ツリーを使用します。

3.詳細なB +ツリー(B +ツリー)

B +ツリー
B +ツリーはBツリーのバリアントです。主な変更点は、親ノードがリーフノードの参照列とインデックス列のみを格納し、すべてのデータがリーフノードにのみ格納されることです。データの冗長性はありますが、ツリー全体が向上します。ストレージ容量。

B +ツリー
この図から、非常に多くのデータがある場合、ノードとしてメモリに特定の量のデータが読み込まれ、最大で3回ディスクと対話することによってのみ照会できることがわかります。システムとメモリ間の対話速度は、ディスクの対話速度よりもはるかに高速です。 。したがって、mysqlはB +ツリーをインデックス構造として使用します。

たとえば、長整数IDを主キーインデックスとして設定して、ツリーの容量を計算しましょう。

最初に、各ノードのmysqlのサイズ設定を確認します。

SHOW GLOBAL STATUS LIKE 'INNODB_PAGE_SIZE'

ここに画像の説明を挿入
mysqlの各ノードのデフォルトサイズは16384バイト(16KB)です。

長整数IDは8バイトのサイズを占有し、B +ツリーの各データはリーフノードデータ(6バイト)を指すアドレスを格納します

親ノードの各ノードが保存できるインデックスの数:

16384 /(8 + 6)= 1170インデックス。

現時点では、計算ツリーの高さは3レベルです。制限内では、保存できるデータの量は次のとおりです。

1170 * 1170 = 1368900リーフノード

各リーフノードのサイズは16kbで、保存できるデータの量は次のとおりです。

1170 1170 16 = 21902400kb = 20GBのデータ

各データのサイズが1kbの場合、格納できるデータの数は次のとおりです。

1170 1170 16 /(16/1)= 21902400

つまり、3回の検索で約2,000万個のデータを見つけることができるため、B +ツリーをデータベースインデックスとして使用してすばやく検索できます。

B +ツリー検索プロセス:

1.ディスクから16kbのサイズのノードファイルを一度に読み込みます。ノードには、インデックス列のデータと下位ノードの参照アドレスが含まれます(長整数IDの場合、一度に1170個のデータが読み込まれます)。

2.読み取ったデータを1つずつ比較し(ツリー構造は親ノードのデータを等間隔に配置します)、検索する値が2つのデータ範囲の真ん中にある場合は、子ノードを探します。

3.葉ノードでない場合は、引き続き(1)に従って比較して子ノードを見つけ、葉ノードの場合は葉ノードを比較してデータを見つけます。

たとえば、
ここに画像の説明を挿入
データ11が7〜13の場合は、子ノードを探して下に移動し、子ノードを比較します。データが11以上の場合は、赤い線を押して、11が見つかるまで下方向に検索を続けます。

葉ノード間のポインタの役割

ここに画像の説明を挿入
すべてのリーフノードが隣接するリーフノードへのポインタを格納していることがわかります。

そのようなSQLステートメントがあるとします(ここで、age列はインデックス列です)。

select * from user where age >20

インデックス列は順番に配置されているため、臨界値20が見つかった場合、次のデータは要件を満たしている必要があります。リーフノードポインターを使用すると、代わりに、ポインターを使用して別のノードのデータをすばやく見つけることができます。親ノードに戻り、もう一度検索してください!

これは、mysqlデータベースがデフォルトでハッシュアルゴリズムを使用しない理由の1つでもあります(ハッシュアルゴリズムは、ハッシュマッピングを通じてデータをすばやく見つけることができ、検索速度は非常に高速ですが、範囲検索には適用できません)。

4つの異なるストレージエンジンB +ツリー差分分析

mysqlでは、さまざまな異なるストレージエンジンが提供されています。ストレージエンジンはデータテーブルに関連付けられています。MySQLはデフォルトでinnodbストレージエンジンです。myisamも一般的に使用されます。異なるストレージエンジンのB +ツリーのストレージ方法は少し異なります。

1.クラスター化インデックス(クラスター化インデックス)と非クラスター化インデックスの違い

  • クラスター化インデックス:データはインデックスの並べ替え規則に従って直接格納され、リーフノードは直接すべてのデータです。
  • 非クラスター化インデックス:インデックスは個別に保存され、リーフノードはデータ参照のみを保存します。

2. myisamストレージエンジン

myisamストレージエンジンB +ツリーのリーフノードには、データ全体ではなく、現在のデータ参照のみが保存され、インデックスファイルはデータファイルとは別に保存されます。

つまり、myisamストレージエンジンのデータは個別に保存され、特定の順序で並べ替えられません。データを見つけるには、最初にインデックスファイルのB +ツリーからリーフノードを見つけ、リーフノードが現在のレコードのアドレスに直接アドレスを介して続きますデータの方向性。

したがって、Myisamのインデックスは非クラスター化インデックスです。テーブルには1億分の1のインデックス(主キー)がありません。同時に、同じロック参照ツリーの高さでより多くのデータを保存できます。

しかし:Myisamは比較的低速なポインタを介してデータを検索し、myisamエンジン自体はトランザクション管理などの多くの機能をサポートしていないため、通常は使用されません。

ここに画像の説明を挿入

3. innodbストレージエンジン

innodbストレージエンジンは、データをリーフノードに順番に直接格納します。リーフノードを見つけることは、データを見つけることを意味します。データは、主キーインデックスに従って並べ替えられ、インデックスと一緒に格納されます。

つまり、Innodbのインデックスとデータは一緒に保存され、アドレスで検索する必要はありません。検索時間は速くなりますが、同じツリーの高さで保存されるデータは少なくなります。Innodbはクラスター化インデックス(主キー)を使用するため、データは特定の順序で並べ替える必要があり、データテーブルに主キーが必要です。主キーがない場合、mysqlは自動的に非表示の主キーを作成してデータを並べ替えて保存します。

ここに画像の説明を挿入
myisamストレージエンジンの主キーの数に関係なく、非クラスター化インデックスの方法で格納されますが、innodbは異なり、主キーはクラスター化インデックスですが、他のインデックスはクラスター化されていませんが、追加のB +ツリーを構築し、インデックス列を格納し、リーフノードを格納しますデータの主キー。次に、主キーインデックスに従ってデータを検索します。

言い換えると、Innodbの他のインデックスを2回検索する必要があり、データに対応する主キーが初めて検索され、対応するデータが主キーを通じて検出されます。

通常のインデックスはアドレスを記録せずに主キーを記録するのは、innodbのデータがソートされるためです。データを挿入すると、ツリー全体の構造が変更される可能性があり、データのアドレスに影響を及ぼし、主キーは決して変更されませんはい、そのため、データは主キーの2回目の検索でのみ見つけることができます。
ここに画像の説明を挿入

さらに、innodbの主キーでは、UUIDの代わりに自動インクリメントされた整数データを使用することをお勧めします。

自己増分データはツリー全体に小さな影響を与え、UUIDは不確実なハッシュ値を持っているので、左から1つと右から1つを挿入することが可能です。これはツリー全体の構造に大きな影響を与え、速度が遅くなります。さらに、検索時にUUIDをハッシュと比較し、整数データを直接比較すると、整数データの比較が高速になります。

ここに画像の説明を挿入
ここに画像の説明を挿入

インデックスの本質は、MySQLクエリデータがテーブル全体のスキャンを実行することを回避することであり、ディレクトリ構造に似た形式でデータをすばやく見つけることです。インデックス付けにより、データ検索の速度が大幅に向上しますが、インデックスが多すぎると、ディスク領域を消費し、無駄が生じ、インデックスを合理的に構築します。このチュートリアルがインデックスの理解に役立つことを願っています。ご覧いただきありがとうございます。

おすすめ

転載: blog.csdn.net/qq_42628989/article/details/106652538