MySQLのパフォーマンス[インデックス最適化分析]

SQLパフォーマンスの低下

SQLパフォーマンスが低下するいくつかの理由:

  • 悪いSQL
  • インデックスは使用されていますが、インデックスが無効です
  • 関連するクエリの結合が多すぎる(設計上の欠陥または避けられない要件)
  • サーバーのチューニングとさまざまなパラメーター設定(バッファー、スレッドサイズの設定など)

結合クエリ

MySQL SQLステートメントの実行順序
ここに画像の説明を挿入

総括する
ここに画像の説明を挿入

7種類の結合クエリ

// 内连接两表共有内容
select * from emp a inner join dept b on a.deptId=b.id
// 左连接左表全有 && 两表共有内容
select * from emp a left join dept b on a.deptId=b.id
// 右连接右表全有 && 两表共有内容
select * from emp a right join dept b on a.deptId=b.id
// 左连接 左表独有内容
select * from emp a left join dept b on a.deptId=b.id where b.id is null
// 右连接 右表独有内容
select * from emp a right join dept b on a.deptId=b.id where a.deptId is null
// 全连接 两表全部内容【union 去除重复数据】
select * from emp a left join dept b on a.deptId=b.id
union
select * from emp a right join dept b on a.deptId=b.id
// 全连接 两表独有内容
select * from emp a left join dept b on a.deptId=b.id where b.id is null
union
select * from emp a right join dept b on a.deptId=b.id where a.deptId is null

索引の紹介

公式定義:インデックスインデックスは、MySQLが効率的にデータを取得するのに役立つデータ構造です。したがって、結論を出すことができます。**索引的本质就是数据结构。**

インデックスとは何ですか?

排好序的快速查找数据结构

データベースは、データ自体に加えて、特定の検索アルゴリズムを満たすデータ構造も維持します。これらのデータ構造は特定の方法でデータをポイントするため、これらのデータ構造に基づいて高度な検索アルゴリズムを実装できます。このデータ構造はインデックスです。

一般に、インデックス自体も非常に大きく、すべてをメモリに格納することは不可能であるため、インデックスはインデックスファイルの形式でディスクに格納されることがよくあります。

通常、私たちが参照するインデックスは、特に指定がない限り、Bツリー(複数の検索ツリー、必ずしもバイナリではない)構造によって編成されたインデックスを参照します。その中で、クラスター化インデックス、セカンダリインデックス、カバーインデックス、複合インデックス、プレフィックスインデックス、一意のインデックスはすべて、デフォルトでB +ツリーインデックスを使用し、まとめてインデックスと呼ばれます。B +ツリータイプのインデックスに加えて、ハッシュインデックス(ハッシュ、インデックス)などがあります。

索引付けの利点

大学図書館での書誌索引の確立と同様に、データ検索の効率が向上し、データベースのIOコストが削減されます。
インデックス列でデータを並べ替えると、データの並べ替えのコストが削減され、CPUの消費量が削減されます

インデックスの欠点

実際、インデックスは、主キーとインデックスフィールドを格納するテーブルでもあり、エンティティテーブルのレコードをポイントするため、インデックス列も領域を占有します。

インデックスによりクエリの速度が大幅に向上しますが、テーブルの挿入、更新、削除など、テーブルの更新速度も低下します。テーブルを更新すると、MySQLはデータを保存するだけでなく、インデックスファイルが更新されてインデックスカラムフィールドが追加されるたびにインデックスファイルも保存するため、更新によってキー値が変更された後にインデックス情報が調整されます。

インデックスは効率向上の要因にすぎません。MySQLに大量のデータを含むテーブルがある場合、最適なインデックスの調査と確立、またはクエリの最適化に時間を費やす必要があります。

mysqlインデックス分類

  • 単一インデックス

即一个索引只包含单个列,一个表可以有多个单列索引。

  • 一意のインデックス

索引的值必须是唯一的,但允许有空值。

  • 複合インデックス

即一个索引包含多个列

  • 基本的な文法
// 单独创建索引
create [unique] index indexName ON mytable(columnName(length));
// 创建表的同时创建索引
alter mytable add [unique] index [indexName] ON (columnName(lenght));
// 删除索引
drop index [indexName] ON mytable;
// 查看索引
show index from table_name;

データテーブルのインデックスを追加する4つの方法:

// 该语句添加一个主键,这意味着索引值必须是唯一的,且不能为 NULL
ALTER table table_name ADD PRIMARY KEY(column_list);
// 该语句创建索引的值必须是唯一的(除了NULL外,NULL可能会出现多次)。
ALTER table table_name ADD UNIQUE index_name(column_list);
// 添加普通索引,索引值可出现多次。
ALTER table table_name ADD INDEX index_name(column_list);
// 该语句指定了索引为 FULLTEXT,用于全文索引
ALTER table table_name ADD FULLTEXT index_name(column_list);

mysqlインデックス構造

BTree 索引

Hash 索引

full-text 全文索引

R-Tree 索引

インデックスを作成する必要がある状況

  1. 主キーは自動的に一意のインデックスを作成します
  2. クエリ条件として頻繁に使用されるフィールドにはインデックスを付ける必要があります
  3. クエリ内の他のテーブルに関連付けられているフィールドをクエリし、外部キー関係のインデックスを作成します
  4. 単一キー/複合インデックス選択の問題(同時実行性が高いと、複合インデックスが作成される傾向があります)
  5. クエリの並べ替えフィールドで、インデックスを使用して並べ替えフィールドにアクセスすると、並べ替えの速度が大幅に向上します。
  6. クエリの統計またはグループ化フィールド。

インデックスを作成しない場合

  1. 頻繁に更新されるフィールドは、インデックスの作成には適していません
  2. Where条件で使用されていないフィールドはインデックス付けされません
  3. テーブルフィールドが少なすぎます
  4. 繰り返して均等に分散されたデータを持つテーブルフィールド。したがって、最も頻繁に照会され、最も頻繁にソートされるデータのインデックスのみを作成する必要があります。データ列に多くの重複コンテンツが含まれている場合、インデックスを作成しても実用的な効果はあまりありません。

パフォーマンス分析

MySqlクエリオプティマイザー

  1. MySQLには、SELECTステートメントの最適化に特化したオプティマイザモジュールがあります。その主な機能は、計算および分析システムで収集された統計情報を提供して、クライアントが要求したクエリに最適な実行プランを提供することです。この部分が最も時間がかかります。
  2. クライアントがMySQLからクエリをリクエストすると、コマンドパーサーモジュールはリクエストの分類を完了します。違いがSELECTでMySQLクエリオプティマイザーに転送されると、MySQLクエリオプティマイザーは最初にクエリ全体を最適化し、いくつかの定数式のバジェットを処理します。定数値に直接変換します。そして、いくつかの役に立たないか明らかな条件の削除、構造調整など、クエリのクエリ条件を単純化して変換する。次に、クエリ内のヒント情報(存在する場合)を分析して、ヒント情報を表示することでクエリの実行プランを完全に決定できるかどうかを確認します。ヒントがない場合、またはヒント情報が実行プランを完全に決定するのに十分でない場合、関連するオブジェクトの統計情報が読み取られ、対応する計算と分析がクエリに従って書き込まれ、最終的な実行プランが取得されます。

MySQLの一般的なボトルネック

  1. CPU:CPU在饱和的时候一般发生在数据装入内存或从磁盘上读取数据的时候。
  2. 私:磁盘 I/O 瓶颈发生在装入数据远大于内存容量的时候。
  3. サーバーハードウェアのパフォーマンスボトルネック:top,free,iostat和vmstat来查看系统的性能状态

説明する

Explain 又称为 【查看执行计划】

Explainキーワードを使用して、MySQLがSQLステートメントを処理する方法を知るために、オプティマイザによって実行されるSQLクエリをシミュレートします。クエリまたはテーブル構造のパフォーマンスボトルネックを分析します。

Explainの使い方

explain + SQL 语句

ここに画像の説明を挿入
含まれる情報:

id select_type テーブル タイプ possible_keys キー key_len ref 追加

説明の役割

  1. 查看表的读取顺序
  2. 查看数据读取操作的操作类型
  3. 查看哪些索引可以使用
  4. 查看哪些索引被实际使用
  5. 查看表之间的引用关系
  6. 查看每张表有多少行被优化器查询

ExplainのIDフィールド関数

クエリ内で選択句または演算テーブルが実行される順序を示す、一連の番号を含む選択クエリのシーケンス番号

idフィールドには3つの状況があります。

  1. IDは同じで、実行順序は上から下です
  2. IDが異なります。サブクエリの場合、IDのシリアル番号が増加します。ID値が大きいほど、優先度が高く、実行は早くなります
  3. 同じIDですが異なります

idが同じ場合は、グループと見なして上から下
順番に実行できます。すべてのグループで、id値が大きいほど優先順位が高くなり、実行が早くなります。
微分= DERIVED

Explainのselect_typeおよびテーブルフィールド関数

select_typeの一般的な値:

id select_type
1 シンプル
2 一次
サブクエリ
4 派生
5 連合
6 ユニオン結果

クエリのタイプは主に区別に使用されます。
通常のクエリ、共同クエリ、サブクエリなどの複雑なクエリ。

  1. SIMPLE:単純な選択クエリ、クエリにはサブクエリまたはユニオンが含まれていません
  2. PRIMARY:クエリに複雑なサブパートが含まれている場合、最も外側のクエリがプライマリとしてマークされます
  3. サブクエリ:サブクエリは選択リストまたは場所リストに含まれます
  4. DERIVED:fromリストに含まれるサブクエリは、DERIVED派生としてマークされます。MySQLはこれらのサブクエリを再帰的に実行し、結果を一時テーブルに配置します。
  5. UNION:ユニオンの後に2番目の選択が表示される場合、ユニオンとしてマークされます。ユニオンがfrom句のサブクエリに含まれる場合、外側の選択はDERIVEDとしてマークされます。
  6. UNION RESULT:ユニオンテーブルの選択から結果を取得します

table:この行のデータに関するテーブルを示します。

Explainのタイプフィールド関数

typeはアクセスタイプの配置を示し、typeはアクセスのタイプを示します。これは、より重要なインジケータである結果です。值从最好到最坏依次是:

system>const>eq_ref>ref>fulltext>ref_or_null>index_merge>unique_subquery>index_subquery>range>index>ALL

system> conft> eq_ref> ref> range> index> ALL

一般的に言えば、クエリが少なくとも範囲レベル、できればrefに到達するようにする必要があります。

タイプの一般的な値:

すべて インデックス 範囲 ref eq_ref const、system ヌル

使用されているクエリのタイプを表示します。从最好到最差依次是:
system>const>en_ref>ref>range>index>ALL

  1. system:テーブルにはレコードが1行しかありません(システムテーブルと同じ)。これはconstタイプの特別な列であり、通常は表示されません。これも無視できます。
  2. const:インデックスによって1回検出できることを意味します。constは、主キーまたは一意のインデックスを比較するために使用されます。一致するデータは1行だけなので、非常に高速です。主キーがwhereリストに配置されている場合、MySQLはクエリを定数に変換できます。
  3. ep_ref:一意のインデックススキャン。各インデックスキーについて、テーブルに一致するレコードは1つだけです。主キーまたは一意のインデックススキャンで一般的に使用されます。
  4. ref:一意ではないインデックススキャンは、単一の値に一致するすべての行を返しますが、本質的にはインデックスアクセスです。単一の値に一致するすべての行を返しますが、複数の適格な行を見つける場合があります。したがって、彼は検索とスキャンのハイブリッドである必要があります。
  5. 範囲:特定の範囲の行のみをチェックし、インデックスを使用して行を選択します。キー列は、使用されるインデックスを示します。通常、between、<、>、inなどのクエリがwhereステートメントに表示されます。この範囲スキャンインデックスは、インデックスの特定のポイントでのみ開始する必要があるため、全テーブルスキャンよりも高速です。 、すべてのインデックスをスキャンせずに、別のポイントで終了します。
  6. インデックス:フルインデックススキャン。インデックスとALLの違いは、インデックスタイプがインデックスツリーのみをトラバースすることです。インデックスファイルは通常データファイルよりも小さいため、これは通常ALLよりも高速です。(つまり、すべてとIndexは両方ともテーブル全体を読み取りますが、indexはインデックスから読み取られ、すべてはハードディスクから読み取られます)
  7. all:全表スキャン。一致する行を見つけるために表全体を走査します。

Explainの可能なキーとキーフィールド関数

  • possible_keys

このテーブルに適用できる1つ以上のインデックスを表示します。
インデックスがある場合、フィールドに関連するクエリ但不一定要被查询实际使用インデックスがリストされます。

  • キー

実際に使用されるインデックス。NULLの場合、インデックスは使用されません。
查询中若使用了覆盖索引,则该索引仅出现在 key 列表中

Explainのkey_lenフィールド関数

インデックスで使用されるバイト数を示します。この列を使用して、クエリで使用されるインデックスの長さを計算できます。精度を失うことなく、長さが短いほど良いです。
key_lenによって表示される値は、インデックスフィールドの可能な最大長です并非实际使用长度。つまり、key_lenは、テーブルから取得されるのではなく、テーブル定義に従って計算されます。

Explainの参照フィールド関数

インデックスのどの列が、可能であれば定数として使用されるかを示します。インデックス付きの列の値を見つけるために使用される列または定数。

クエリ内の他のテーブルに関連付けられているフィールドをクエリし、外部キー関係のインデックスを作成します

Explainの行フィールド関数

テーブルの統計とインデックスの選択に応じて、必要なレコードを見つけるために読み取る必要がある行の数を概算します

Explainフィールド関数を説明する

追加の重要な情報を記録する

一般的な値は次のとおりです。

  1. Using filesort:これは、Mysqlがテーブル内のインデックスの順序に従ってデータを読み取るのではなく、外部インデックスを使用してデータをソートすることを意味します。MySQLでインデックスを使用して実行できないソート操作は、「ファイルソート」と呼ばれます。
  2. Using temporary:一時テーブルは中間結果を保存するために使用され、MySQLはクエリ結果をソートするときに一時テーブルを使用します。一般に、並べ替え順とクエリのグループ化グループで使用されます。
  3. Using index:表のデータ行へのアクセスを回避するために、対応する選択操作でカバリングインデックス(Covering Index)が使用され、効率が良いことを示します。whereを同時に使用する場合は、インデックスを使用してインデックスキー値を検索することを示します。whereを同時に使用しない場合は、検索を実行する代わりにインデックスを使用してデータを読み取ることを示します。覆盖索引(Covering Index)

カバーするインデックス:selectのデータ列は、データ行を読み取らずに、インデックスからのみ取得できます。MySQLは、インデックスを使用して、selectリスト内のフィールドを返すことができます。インデックスに従ってデータファイルを再度読み取る必要はありません。查询列要被所创建的索引覆盖。

注:カバリングインデックスを使用する場合は、select *からではなく、selectリストから必要な列のみを取り出してください。すべてのフィールドが一緒にインデックス付けされると、インデックスファイルが大きくなり、クエリのパフォーマンスが低下します。

  1. Using where:SQLがフィルタリングを使用することを示します。
  2. using join buffer:このSQLが接続キャッシュを使用することを示します。
  3. impossible where:SQLステートメントのwhere句の値が常にfalseであり、タプルの取得に使用できないことを示します。
  4. select tables optimized away:group byを使用しない場合、インデックスに基づいて最小/最大操作を最適化するか、MyISAMストレージエンジンのcount(*)操作を最適化します。計算を実行するために実行ステージまで待つ必要はありません。クエリ実行プランの生成ステージが最適化されます。
  5. distinct:個別の操作を最適化し、最初に一致するタプルを見つけた後、同じ価値のあるアクションの検索を停止します。

インデックスの最適化

インデックス分析

  • 単一テーブル分析:フィールドをクエリしてインデックス最適化を適切に構築するために一般的に使用されます。
  • 2つのテーブルの分析:左側の結合インデックスは右側のテーブルに作成し、右側のテーブルは左側のテーブルに作成することをお勧めします。逆に、相互にインデックスを作成することで最適化できます。
  • 3つのテーブルの分析:2つのテーブルと同じですが、他の2つのテーブルとは逆に、インデックスの最適化を作成します。

インデックスの失敗

  1. 完全一致
  2. 最適な左プレフィックスルール

インデックスに複数の列が含まれている場合は、左端の接頭辞ルールに従います。つまり、クエリはインデックスの左端の最前列から始まり、インデックス内の列をスキップしません。

  1. インデックス列に対して操作(計算、関数、自動または手動の型変換)を行わないでください。インデックスが失敗し、フルテーブルスキャンに切り替わります。
  2. ストレージエンジンは、インデックスの範囲条件の右側にある列を使用できません
  3. カバリングインデックスを使用してみてください(インデックスクエリ(インデックス列とクエリ列)へのアクセスのみ)。選択を減らします*
  4. MySQLは、インデックスが(!=または<>)でない場合、インデックスを使用できません。これにより、テーブル全体がスキャンされます。
  5. is null、is not null、またインデックスを使用できません
  6. 同様のワイルドカードは%( '%abc ...')で始まり、mysqlインデックスの失敗は全表スキャン操作になります。
  7. 一重引用符のない文字列のインデックスは無効です。
  8. インデックスを使用して接続すると、インデックスが失敗します。

インタビューの質問:「%abc%」のようにインデックスが無効でないという方法を解決するにはどうすればよいですか?
likeクエリ中にインデックスが失敗しないようにするための前提条件は、%が文字列の右側に追加されることです。たとえば、 'abc%'により、インデックスは無効になりませんが、現在の条件は、 '%などの完全なあいまいクエリを作成する必要があることです。 abc% '、この方法でインデックスを書き込むと100%失敗します。この問題を解決するにはどうすればよいですか?

カバリングインデックスを追加して最適化することができます。たとえば、クエリ条件が名前である場合、フィールドにインデックスを追加します。たとえば、
select * from table where name like '%abc%';
Explain analysis、the above sql is not usedインデックス、
'%abc%'のような名前のテーブルからこのSQL 選択名を変更できます。
上記のSQLを再度分析した後、最終的にインデックスが実際に使用されていることがわかります。これにより、類似した完全なファジークエリが使用されている場合でも、解決されますインデックス障害の問題。
**这里要注意的事情:覆盖索引优化的前提是 select 查询的字段正好和你的索引字段数量一致的前提下,简单来说:覆盖索引字段和你select 的字段一致或小于其字段。**

一般的なアドバイス

  1. 単一キーインデックスの場合は、現在のクエリのフィルタリングパフォーマンスが向上するインデックスを選択してください。
  2. 複合インデックスを選択する場合、現在のクエリで最もフィルタ可能なフィールドはインデックスフィールドシーケンスにあり、位置が高いほど優れています。
  3. 複合インデックスを選択するときは、現在のクエリのwhere句でより多くのフィールドを含むことができるインデックスを選択してください。
  4. 統計情報を分析し、クエリの表現を調整して、適切なインデックスを選択する目的を達成してください。

おすすめ

転載: blog.csdn.net/qq_43647359/article/details/105822524