「効率的なインデックス作成スキル: インデックスの分類、MySQL インデックスの使用、左端一致の原則、テーブル リターン クエリ、テーブル リターンを回避する方法、インデックス プッシュダウン、インデックス作成時の注意事項」

索引

MySQLインデックスの分類

1. 通常インデックスとユニークインデックス

通常のインデックス: MySQL の基本的なインデックス タイプで、インデックスを定義するカラムに重複値や NULL 値を挿入できます
一意のインデックス: インデックス カラムの値は一意である必要がありますが、NULL 値は
一意の
主キー インデックスは、NULL 値を許可しない特別な一意のインデックスです

2. 単一列インデックスと複合インデックス

単一列インデックス: インデックスには 1 つの列のみが含まれ、テーブルには複数の単一列インデックスを含めることができます
結合インデックス: テーブル内の複数のフィールドを組み合わせて作成されたインデックス 複数の単一列インデックス
複数の単一列インデックスを使用してクエリを実行する場合条件に応じて、オプティマイザは最適なインデックス戦略を選択します。インデックスを 1 つだけ使用することも、複数のインデックスを使用することもできます。ただし、複数の単一列インデックスを使用すると、下部に複数の B+ インデックス ツリーが構築され、ディスク領域が占有され、検索効率が一定量無駄になります。索引!

3. 全文インデックス

フルテキスト インデックスのタイプはフルテキストで、インデックス
が定義されている列の値の全文検索をサポートし、これらのインデックス列に重複値や null 値を挿入できます。
テキスト インデックスは、char、varchar、text 型の列に作成できます。

4. 空間インデックス

空間インデックスは、空間データ型のフィールドに確立されたインデックスです
。MySQL には、Geometry、Point、Linestring、Polygon という 4 つの空間データ型があります。MySQL は、
Spatial キーワードを使用してそれを拡張し、作成と同様の構文を使用して空間を作成できるようにします。通常のインデックス
空間インデックスの作成に使用されるインデックス列は NULL 値を許可せず、MyISAM テーブルでのみ作成できます。

5. プレフィックスインデックス

char、varchar、text 型の列にインデックスを作成する場合、インデックス列の長さを指定できます。

MySQL インデックスの使用

1. 通常のインデックスに INDEX を追加

ALTER TABLE table_name ADD INDEX index_name ( column )

2. 主キーインデックスに PRIMARY KEY を追加します。

ALTER TABLE table_name ADD PRIMARY KEY ( column )

3. 一意のインデックスに UNIQUE を追加します

ALTER TABLE table_name ADD UNIQUE ( column )

4. フルテキスト インデックスに FULLTEXT を追加する

ALTER TABLE table_name ADD FULLTEXT ( column )

5. 複数列インデックスの追加

ALTER TABLE table_name ADD INDEX index_name ( column1, column2, column3 )

6. インデックスの削除

table_name のインデックス Index_name を DROP します;``

7. インデックスを見る

テーブル名からインデックスを表示;

左端のマッチング原則

左端の優先順位。左端から始まる任意の連続インデックスと一致します。同時に、範囲クエリ (>、<、between、like) が発生すると、マッチングは停止します。
すべての列を一致させる場合:
student テーブル:

CREATE TABLE `student` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `gid` int(11) NOT NULL,
  `cid` int(11) DEFAULT NULL,
  `uid` int(11) DEFAULT NULL,
  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uni_Gid_Cid_SId` (`gid`,`cid`,`uid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

結論: クエリ列の順序を変更しても、同じ結果が得られます。これは、MySQL がオプティマイザーを通じてインデックスの順序を自動的に最適化するためです。

#ALTER TABLE index user_index on user(name,sex,age)
#可以使用复合索引:索引中包含的最左侧字段,只是顺序不正确,在执行的时候可以动态调整为最前左缀,下列执行计划type为ref
select * from user where sex = ? and age = ? and name = ?
select * from user where age = ? and name = ?

#不可以使用复合索引:因为缺少左侧字段
select * from user where sex = ? and age = ? 
select * from user where age = ?
select * from user where sex = ? 
#当缺少左侧字段时,不使用*,使用具体需要的复合索引字段时 依旧会走索引 此时执行计划的type为index
select name,sex,age from user where sex = ? and age = ?

左端のサフィックス原則はスキップスキャンによって打破できる この知識を簡単に整理してみます
これは8.0で最適化されました
MySQLバージョン8.0ではインデックススキップスキャンの機能が追加され始めました 最初のカラムの一意の値の数がインデックスが小さい場合、where 条件に最初の列インデックスがない場合でも、クエリ時に結合インデックスを使用できます。たとえば、使用するジョイント インデックスは bcd ですが、b のフィールドは比較的少ないです。ジョイント インデックスを使用するときは b を使用しませんが、引き続きジョイント インデックスを使用できます。MySQL ジョイント インデックスは、左端のプレフィックス マッチング原則に従う場合があります。 、そうでない場合もあります。

テーブルクエリを返す

これは、InnoDB のインデックス実装から始まります。InnoDB には、次の 2 つの主要なタイプのインデックスがあります。

  • クラスター化インデックス
  • セカンダリインデックス

InnoDB クラスター化インデックスと通常のインデックスの違い:

InnoDB クラスター化インデックスのリーフノードには行レコードが格納されるため、InnoDB にはクラスター化インデックスが 1 つだけ必要です。

  1. テーブルで PK が定義されている場合、そのPK はクラスター化インデックスです
  2. テーブルで PK が定義されていない場合、最初の NULL でない一意の列はクラスター化インデックスになります。
  3. それ以外の場合、InnoDB はクラスター化インデックスとして非表示の row-idを作成し、
    InnoDB の通常インデックスのリーフ ノードに主キー値が格納されます。

クラスター化インデックスと通常のインデックスのデータ構造は両方とも b+ ツリーであり、すべてのデータがリーフ ノードに格納され、リーフ ノード間を指すポインターがあることを特徴とします。

たとえば、次のようなテーブルを作成することもできます:
t(id PK, name KEY, sex, flag);
id はクラスター化インデックス、name は通常のインデックスです。
テーブルには 4 つのレコードがあります。

1, shenjian, m, A
3, zhangsan, m, A
5, lisi, m, A
9, wangwu, f, B

クラスター化インデックスと通常のインデックスは次のとおりです。
[写真]

通常のインデックスを使用してデータを検索する場合、インデックス以外に他の列フィールドがある場合、検索はクラスター化インデックスで行われます。
select * from t where name='lisi'; # 该语句执行流程如下图
ここに画像の説明を挿入します

これはいわゆるテーブル リターン クエリであり、最初に主キー値を見つけてから行レコードを見つけますが、そのパフォーマンスはインデックス ツリーをスキャンするよりも低くなります。

テーブルリターンを回避する方法

カバーするインデックスを使用できます。例: 既存の User テーブル

CREATE TABLE `user`
(
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name`  int(11)     DEFAULT NULL,
  `sex`  char(3)     DEFAULT NULL,
  `address`  varchar(10) DEFAULT NULL,
  `hobby`  varchar(10) DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  KEY `i_name` (`name`)
) ENGINE = InnoDB;

名前と性別を頻繁にクエリする必要があるシナリオがあります。name
= 'zhangsan' のユーザーから id、名前、性別を選択します。
このステートメントはビジネスでよく使用され、ユーザー テーブルの他のフィールドの使用率ははるかに低くなります。これらの分野よりも。この場合、名前フィールドにインデックスを構築すると、単一のインデックスを使用する代わりに、結合インデックス (名前、性別) が使用されます。この場合、このクエリ ステートメントを再度実行すると、この補助インデックス (名前、性別) に基づいて取得される結果には、必要なクエリ結果のすべてのフィールドの完全なデータが含まれます。

インデックスのプッシュダウン

これは、MySQL 5.6 以降で提供される機能です。select
* from table1 where b like '3%' and c = 3 をクエリする必要があるとします。5.6 より前の
インデックス フィールドは、index(b,c) です。

  • まずジョイント インデックスを通じて 3 で始まるデータをクエリし、次に主キーを取得します (上の図のシアンのブロックが主キーです)。
  • 次に、主キーを使用して主キー インデックスに移動し、テーブルに戻ってセカンダリ インデックスをクエリします。3 で始まるいくつかのクエリを実行し、テーブルに数回戻ります。

5.6以降

  • まず、セカンダリ インデックスを通じて 3 で始まるデータをクエリし、次に c = 3 のデータを見つけてフィルタリングし、主キーを取得します。
  • 主キーを使用してテーブルにクエリを返します。上記はすべてテーブルにクエリを返しますが、5.6 より前では、2 次キャッシュはデータ フィルタリングに完全には使用されていませんでした。3 で始まるデータが大量にある場合は、テーブルに戻り続けるためです。しかし、5.6 以降、
    クエリに後続のインデックス フィールドを使用することについてはどう思いますか?
    そのため、インデックス プッシュダウンは結合インデックスとともに使用する必要があります。したがって、インデックス プッシュダウンを使用せずに、のフィールドを最大限に活用することになります。結合インデックスを使用してフィルタリングを行い、テーブルに返す必要があるデータを最小限に抑えてクエリの効率を向上させるというアイデアは非常にシンプルです。

インデックスの失敗を回避する方法

  • 結合インデックスを使用する場合は、左端の一致原則に従います。
  • インデックス列に対して、計算、関数、型変換などの操作を実行しないでください。
  • カバリングインデックスを使用してみる
  • 等しくない (!= / <>) 条件、ワイルドカード (%abc など) で始まるファジー クエリ、またはインデックス列の結合条件としては使用しないようにしてください。
  • 文字列に一重引用符を追加します (追加しない場合、インデックス列の暗黙的な変換が発生し、インデックスが失敗する可能性があります)

各列の機能を説明します

ここに画像の説明を挿入します
ここに画像の説明を挿入します

(1) id : テーブルの読み取り順序、またはクエリ内で select 句が実行される順序を反映します。
①IDが同じ場合、実行順序は上から下となります。
② ID が異なる サブクエリの場合は ID の通番がインクリメントされ、ID の値が大きいほど優先順位が高く、先に実行されます。
③ id が同じ場合はグループとみなし、上から順に実行されますが、グループ全体の中で id の値が大きいほど優先順位が高く、先に実行されます。

(2) select_type : select の種類を示し、主に通常のクエリ、結合クエリ、サブクエリなどの複雑なクエリを区別するために使用されます。
① シンプル: サブクエリやユニオンを含まない単純な選択クエリです。
② プライマリ: クエリに複雑なサブパートが含まれる場合、最も外側のクエリがプライマリとしてマークされます。
③ サブクエリ: select または where リスト内のサブクエリ。
④ Derived: from リストに含まれるサブクエリについて、MySQL はこれらのサブクエリを再帰的に実行し、結果を一時テーブルに格納します。
⑤ Union: 2 番目の select が Union の後に出現する場合、それは Union としてマークされ、union が from 句のサブクエリに含まれる場合、外側の select は派生としてマークされます。
⑥結合結果:結合後の結果セット。

(3) table : このステップでアクセスしたデータベース内のテーブル名を表示します(この行のデータがどのテーブルを参照しているかを表示します)。実際のテーブル名ではない場合がありますが、実行結果の略称である場合があります。いくつかのステップの実行。

(4) type : テーブルへのアクセス方法。MySQL がテーブル内で必要な行を見つける方法を示し、「アクセス タイプ」とも呼ばれます。一般的なアクセス タイプには、ALL、インデックス、範囲、ref、eq_ref、const、system、および NULL が含まれます (左から右へ、パフォーマンスは最悪から最高)。
① ALL: フル テーブル スキャン。MySQL はテーブル全体を走査して一致する行を見つけます。
② Index:: フル インデックス スキャン。インデックスと ALL の違いは、インデックス タイプがインデックス ツリーのみをスキャンすることです。
③ Range: インデックス範囲スキャン。指定された範囲のみを取得する行のバッチを返し、インデックスを使用して行を選択します。一般に、 between、<、>、in などのクエリは where ステートメントに現れます。このレンジ スキャン インデックスは、インデックス全体をスキャンする必要がなく、インデックス内の特定のポイントで開始し、別のポイントで終了するだけでよいため、フル テーブル スキャンよりも優れています。
④ ref: 非固有インデックス スキャン。単一の値に一致するすべての行を返します。本質的にはインデックス アクセスです。単一の値に一致するすべての行を返します。ただし、条件を満たす複数の行が見つかる可能性があります。検索とスキャンを組み合わせたものになります。
⑤ eq_ref: ref と似ていますが、使用されるインデックスが一意のインデックスである点が異なり、各インデックス キーに対して、テーブル内の 1 つのレコードのみが一致するという点が主キーまたは一意のインデックス スキャンで一般的です。簡単に言うと、複数テーブル接続時の関連付け条件として主キーまたは一意キーが使用されます。
⑥ const、system: MySQL がクエリの特定の部分を最適化し、定数に変換する場合にアクセスするためにこれらの型を使用します。クエリ条件で定数を使用する場合、定数はインデックスを通じて一度だけ見つけることができ、多くの場合、主キーまたは一意を使用してインデックスに表示されます。System は const 型の特殊なケースで、クエリされたテーブルに行が 1 つしかない場合に使用されます。
⑦ NULL: MySQL は最適化プロセス中にステートメントを分解し、実行中にテーブルやインデックスにアクセスする必要さえありません。たとえば、インデックス列からの最小値の選択は、別のインデックス検索を通じて完了できます。

(5) possible_keys : MySQL がテーブル内の行を検索するために使用できるインデックスを示します。クエリに含まれるフィールドにインデックスがある場合、そのインデックスはリストされますが、必ずしもクエリで使用されるわけではありません。

(6) key : MySQL が実際に使用することを決定したインデックスを表示します。インデックスが選択されていない場合は、NULL が表示されます。MySQL に possible_keys カラムのインデックスの使用または無視を強制するには、クエリで FORCE INDEX または IGNORE INDEX を使用します。クエリでカバー インデックスが使用されている場合 (選択後にクエリされるフィールドが、作成されたインデックス フィールドとまったく同じである)、インデックスはキー リストにのみ表示されます。

(7) key_len : インデックスで使用されているバイト数を表示します。

(8) ref : 上記のテーブルの接続一致条件、つまり、インデックス列の値を検索するためにどの列または定数が使用されるかを示します。

(9) rows : テーブル統計とインデックス選択に基づいて、必要なレコードを見つけるために読み取られる MySQL の行数の推定値を表示します。

(10)追加: この列には、MySQL がクエリを解決する方法の手順と説明が含まれます。これには、他の列での表示には適さないが、実行計画にとって非常に重要な追加情報も含まれます。
① where の使用: テーブル内のすべての情報を読み込まずに、インデックスを通じてのみ必要なデータを取得できます。これは、テーブルの要求されたすべてのカラムが同じインデックス部分にある場合に発生します。これは、MySQL サーバーが行を取得することを意味します。ストレージ エンジンの後、フィルタリングします。
② 一時的な使用: MySQL が結果セットを保存するために一時テーブルを使用する必要があることを示します。MySQL は、クエリ結果を並べ替えるときに一時テーブルを使用します。これは、並べ替え (並べ替え) やグループ クエリ (グループ化) で一般的です。
③ ファイルソートの使用: クエリに操作による順序が含まれており、インデックスを使用してソート操作を完了できない場合、これを「ファイルソート」と呼びます。インデックスを作成するときに、最初にデータがソートされます。一般にファイルソートが使用されるのは、次のような条件があります。順序付け後にインデックスが失敗する場合は、最適化することをお勧めします。
④ 結合バッファの使用: 接続キャッシュを使用することを示します。たとえば、クエリの場合、複数テーブルの結合数が非常に多いため、設定ファイルの結合バッファを増やします。この値が表示される場合は、クエリの特定の状況によっては、インデックスを追加して改善する必要がある場合があることに注意してください。
⑤ インデックスの使用: テーブル内の列情報を取得するために実際の行を読み取るためにさらに検索を行わずに、インデックス ツリー内の情報のみを使用します。テーブルのデータ行へのアクセスを回避するために、対応する選択操作でカバリング インデックスが使用され、非常に効率的です。カバーインデックス: 選択されたデータ列は、データ行を読み取らずにインデックスからのみ取得でき、作成されたインデックスの数 (クエリ列がインデックスの数以下である) および順序と一致します。カバリング インデックスを使用する場合は、使用する必要がある列のみを選択し、select * を使用しないように注意する必要があります。同時に、すべてのフィールドに一緒にインデックスを作成すると、インデックス ファイルが大きくなりすぎてしまうため、パフォーマンスが低下します。
⑥ インデックス条件を使用中: ICP 最適化が実行されていることを示します。

まず、クエリ タイプの type カラムに注目してください。all キーワードが表示されている場合は、テーブル全体がスキャンされ、インデックスは使用されていないことを意味します。キー カラムをもう一度見てください。キー カラムが NULL の場合、それは次のことを意味します。インデックスは使用されません。次に、行列を確認します。この列の値が大きいほど、値も大きくなります。これは、スキャンする必要がある行が多いほど、応答にかかる時間が長くなることを意味します。最後に、列を追加し、パフォーマンスに大きく影響する「ファイルソートの使用」や「一時的な使用」などの単語を避けます。

インデックス作成時の注意点

1.テーブルのインデックスの数を制限します多数の更新操作を含むテーブルの場合、インデックスの数は通常 3 を超えてはならず、多くても 5 を超えてはなりません。インデックスを使用するとアクセス速度が向上しますが、インデックスが多すぎるとデータ更新操作に影響します。
2.値が一方向に増加するフィールド(日付タイプのフィールドなど) にインデックスを構築することは避けてください。複合インデックスの場合は、このタイプのフィールドを先頭に配置しないでください。フィールドの値は常に一方向に増加するため、新しいレコードは常にインデックスの最後のリーフ ページに格納され、リーフ ページのアクセス競合、新しいリーフ ページの割り当て、および中間ブランチ ページの分割が継続的に発生します。さらに、構築されたインデックスがクラスター化インデックスの場合、テーブル内のデータはインデックスの順序で格納され、すべての挿入操作が最後のデータ ページに集中するため、挿入の「ホット スポット」が発生します。
3. 複合インデックスの場合は、クエリ条件に出現するフィールドの頻度に基づいてインデックスを作成します複合インデックスでは、レコードは最初のフィールドによって最初に並べ替えられます。最初のフィールドの値が同じレコードの場合、システムは 2 番目のフィールドの値に従って並べ替えます。以下同様です。したがって、複合インデックスの最初のフィールドのみがクエリ条件に現れ、そのインデックスが使用される可能性があります。したがって、適用頻度の高いフィールドを複合インデックスの前に配置すると、システムはこのインデックスを最大限に使用し、インデックスの役割を果たします
4.使用されなくなったインデックス、またはほとんど使用されないインデックスを削除しますテーブル内のデータが大幅に更新されるか、データの使用方法が変更されると、元のインデックスの一部が必要なくなる場合があります。データベース管理者は、更新操作に対するインデックスの影響を軽減するために、これらのインデックスを定期的に特定して削除する必要があります。
5. クエリでほとんど使用または参照されない列にはインデックスを作成しないでください。これは、これらの列がほとんど使用されないため、インデックスを作成してもしなくてもクエリ速度は向上しないためです逆に、インデックスの追加により、システムのメンテナンス速度が低下し、必要なスペースが増加します;
6.多数の同じ値を持つフィールドにインデックスを作成しないでくださいこれは、クエリ結果ではこれらの列 (人事テーブルの性別列など) の値が非常に少ないため、結果セット内のデータ行がテーブル内のデータ行の大部分を占めるためです。テーブル内で検索する必要があるデータ 行の割合が膨大です。インデックスを増やしても取得速度は大幅に向上しません。7
.インデックスは、テキスト、イメージ、およびビット データ型として定義された列に追加しないでくださいこれは、これらの列のデータ量が非常に多いか、値が非常に少ないためです。
8.変更パフォーマンスが取得パフォーマンスよりもはるかに大きい場合、インデックスを作成すべきではありません修正性能と検索性能は相反するものだからである。インデックスを追加すると、検索パフォーマンスは向上しますが、変更パフォーマンスは低下します。インデックスを減らすと、変更パフォーマンスは向上しますが、検索パフォーマンスは低下します。したがって、変更パフォーマンスが検索パフォーマンスよりもはるかに高い場合は、インデックスを作成しないでください。

おすすめ

転載: blog.csdn.net/qq_45442178/article/details/129711297