MySQL インデックスの設計と最適化の方法

MySQL インデックスの設計と最適化の方法

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

データベース インデックスは、追加の書き込みとストレージ スペースを犠牲にして、データベース テーブルでのデータ取得操作の速度を向上させるデータ構造です。簡単に言えば、索引は本の目次に似ており、そこに記録されたページ番号に基づいて必要なコンテンツをすばやく見つけることができます。 ——Wikipedia の一般的な索引は何ですか?

  • 通常インデックス: 制限のない最も基本的なインデックス
  • ユニークインデックス:「通常のインデックス」と同様ですが、インデックス列の値は一意である必要がありますが、null値が許可されます
  • 主キー インデックス: null 値を許可しない特別なインデックスです。
  • 全文インデックス: MyISAM テーブルにのみ使用できます。大規模なデータの場合、全文インデックスの生成には時間がかかり、スペースも消費されます。
  • 複合インデックス: 複数条件クエリの効率を向上させるために、「最左接頭辞一致原則」に従って複合インデックスを確立できます。

ここでは比較的複雑な組み合わせを例に挙げて、最適化する方法を紹介します。

左端のプレフィックス一致の原則

まず、左端のプレフィックス一致の原則が何であるかを知る必要があります。

最左プレフィックス一致原則とは、データ取得に B+Tree ジョイント インデックスを使用する場合、MySQL オプティマイザは述語 (フィルタ条件) を読み取り、範囲クエリまたは不等クエリに遭遇するまでジョイント インデックス フィールドが作成された順序で右方向に一致させます。このフィールドの後のインデックス列は使用されません。このとき、 key_lenを計算すると、ジョイント インデックスによって実際に使用されているインデックス列を分析できます。

key_lenの計算方法

key_len計算は、インデックスの左端のプレフィックス一致の原則を理解するのにも役立ちます。

key_lenorder byを除いて、結果セットを取得するために使用される選択インデックスの長さ [バイト数] を示します。つまり、 order byでもインデックスが使用される場合、 key_lenは含まれません。

key_lenを計算する前に、基本的なデータ型を確認しましょう (UTF8 エンコードを例にします)。

タイプ占有スペースNULLの追加使用は許可されません
文字1文字は3バイト1バイト
varchar 1文字は3バイト1バイト
整数4バイト1バイト
ちっちゃい1バイト1バイト

テストデータテーブルは次のとおりです。

テーブル `test_table` を作成します (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `a` int(11) デフォルトはNULLではない、
 `b` int(11) デフォルトはNULLではない、
 `c` int(11) デフォルトはNULLではない、
 主キー (`id`)、
 キー `test_table_a_b_c_index` (`a`,`b`,`c`)
)ENGINE=InnoDB デフォルト文字セット=utf8;

ヒットインデックス:

mysql> explain select * from test_table where a = 1 and b = 2 and c = 3;
+----+--------------+-------------+------------+-----------+-------------------------+-------------------------+-----------+--------------------+------------+-------------+
| id | select_type | テーブル | パーティション | タイプ | 可能なキー | キー | キー長 | ref | 行 | フィルター済み | 追加 |
+----+--------------+-------------+------------+-----------+-------------------------+-------------------------+-----------+--------------------+------------+-------------+
| 1 | SIMPLE | test_table | NULL | ref | test_table_a_b_c_index | test_table_a_b_c_index | 12 | const、const、const | 1 | 100.00 | インデックスを使用 |
+----+--------------+-------------+------------+-----------+-------------------------+-------------------------+-----------+--------------------+------------+-------------+

key_len = 12がわかります。これはどのように計算されるのでしょうか?
文字セットは UTF8 なので、1 つのフィールドは 4 バイトを占め、3 つのフィールドは 4 * 3 = 12 バイトになります。

NULL が許可されるかどうか。NULL が許可される場合は、フィールドをマークするために追加のバイトが必要です。異なるデータ型には異なるバイト サイズが必要です。

mysql> ALTER TABLE `test_table` CHANGE `a` `a` INT(11) NULL;
mysql> ALTER TABLE `test_table` CHANGE `c` `c` INT(11) NULL;
mysql> ALTER TABLE `test_table` CHANGE `b` `b` INT(11) NULL;
mysql> explain select * from test_table where a = 1 and b = 2 and c = 3;
+----+--------------+-------------+------------+-----------+-------------------------+-------------------------+-----------+--------------------+------------+-------------+
| id | select_type | テーブル | パーティション | タイプ | 可能なキー | キー | キー長 | ref | 行 | フィルター済み | 追加 |
+----+--------------+-------------+------------+-----------+-------------------------+-------------------------+-----------+--------------------+------------+-------------+
| 1 | SIMPLE | test_table | NULL | ref | test_table_a_b_c_index | test_table_a_b_c_index | 15 | const、const、const | 1 | 100.00 | インデックスを使用 |
+----+--------------+-------------+------------+-----------+-------------------------+-------------------------+-----------+--------------------+------------+-------------+

フィールドが空になることが許可されている場合、 key_len 15 = 4 3 + 1 3 になることがわかります (INT 型が空の場合、余分なバイトを占有します)。

インデックスの最適化

これらの基礎知識があれば、実際の SQL に基づいてパフォーマンスを判断できます。

上記のデータ テーブルを例に、3 つのフィールド a、b、c の結合インデックスを作成します。

SQL ステートメントインデックスするかどうか
select * from test_table where a = 1 and b = 2 and c = 3; を説明します。追加: インデックス key_len: 15 を使用
select * from test_table where a = 1 and b = 2 and c = 3 order by c; を説明します。追加: インデックス key_len: 15 を使用
select * from test_table where b = 2 and c = 3; を説明します。追加: where の使用; インデックス key_len の使用: 15
select * from test_table where a = 1 order by c; を説明します。追加: where の使用; index の使用; filesort の使用 key_len: 5
select * from test_table order by a, b, c; を説明します。追加: インデックス key_len: 15 を使用
select * from test_table order by a, b, c desc; を説明します。追加:インデックスの使用; ファイルソートの使用 key_len:15
select * from test_table where a in (1,2) and b in (1,2,3) and c = 1; を説明します。追加: where の使用; インデックス key_len の使用: 15

通常、実行プランを表示するときに、Extra 列が Using index になっている場合は、オプティマイザーがカバーリング インデックスを使用していることを意味します。

  • SQL1はカバーインデックスを使用でき、パフォーマンスが良好です。
  • SQL2はカバーインデックスを使用してソートを回避できるため、パフォーマンスが向上します。
  • SQL3ではカバーインデックスを使用できますが、where句に基づいてフィルタリングする必要があります。
  • SQL4では部分インデックスaを使用できますが、ソートを避けることができず、パフォーマンスが低下します。
  • SQL5 では、カバーリング インデックスをフルに活用してソートを回避できるため、パフォーマンスが向上します。
  • SQL6 ではカバーリング インデックスを使用できますが、ソートは避けられません (これは、MySQL InnoDB がインデックスを作成するときに昇順をデフォルトとし、インデックスを自動的に降順でソートできないためです)。
  • SQL7 ではカバーリングインデックスを使用できますが、where 句 (非固定値クエリ) に従ってフィルタリングする必要があります。

インデックス仕様を作成する

  • インデックスのメンテナンスのコストを考慮すると、1 つのテーブル内のインデックスの数は 5 を超えてはならず、1 つのインデックス内のフィールドの数も 5 を超えてはなりません。
  • 性別などのカーディナリティの低い列にはインデックスを作成しないでください。 低カーディナリティ列で作成されたインデックス クエリは、特にテーブルを返すコストがある場合、必ずしも完全なテーブル スキャンよりもパフォーマンス上の利点があるわけではありません。
  • 適切に結合インデックスを作成します。(a,b,c) は (a)、(a,b)、(a,b,c) と同等です。
  • カバーリング インデックスを適切に使用すると、IO が削減され、ソートが回避されます。

上記は、MySQL インデックスの設計と最適化の方法の詳細です。MySQL インデックスの設計と最適化の詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • MySQLスケーラブル設計の基本原則
  • プロフェッショナルなMySQL開発設計仕様とSQL記述仕様
  • MySQL のバックアップとリカバリの設計アイデア
  • MySQL 20 の高性能アーキテクチャ設計原則 (収集する価値あり)
  • MySQL データベース設計 3 つのパラダイム例分析
  • MySQL テーブルとデータベース シャーディングのアプリケーション シナリオと設計方法
  • MySQLデータベース設計:Pythonを使ったスキーマ操作方法の詳しい解説
  • MySQLのインデックス設計の原則と一般的なインデックスの違いについて簡単に説明します。
  • 効率的で合理的なMySQLクエリステートメントを設計する方法
  • PHP+MySQL ツリー構造(無制限分類)データベース設計 2 つの例
  • 数百万件のレコードの分散ストレージを実現するための MySQL シャーディングのバッチ クエリ設計パターンの詳細な説明
  • PHP+MySQL投票システムの設計と実装
  • よくある MySQL テーブル設計エラーの概要

<<:  img usemap 属性 中国地図リンク

>>:  フレックスレイアウトは左のテキストオーバーフローを実現し、右のテキストの適応を省略します

推薦する

CSS の記述基準と順序を共有する [すべての人に使用を推奨]

CSSの記述順序1. 位置属性(位置、上、右、z-index、表示、フロートなど) 2. サイズ(...

MySQLループは数千万のデータを挿入する

1. テストテーブルを作成する テーブル `mysql_genarate` を作成します ( `id...

MySQL マルチインスタンス構成のアプリケーションシナリオ

目次MySQL 複数インスタンスマルチインスタンスの概要マルチインスタンスとは何ですか?複数のインス...

Mysql の読み取り/書き込み分離期限切れに対する一般的な解決策

MySQLの読み書き分離の落とし穴読み取りと書き込みの分離の主な目的は、メイン データベースの負荷を...

JSはフロントエンドのページング効果を実現します

この記事の例では、フロントエンドのページング効果を実現するためのJSの具体的なコードを参考までに共有...

Ubuntu サーバーで MySQL を設定し、リモート接続を実装する方法

サーバー: Ubuntu Server 16.04 LSSクライアント: Ubuntu 16.04 ...

Vue コンポーネント化の一般的な方法: コンポーネント値の転送と通信

関連する知識ポイント親コンポーネントから子コンポーネントに値を渡す子コンポーネントから親コンポーネン...

CocosCreator ソースコードの解釈: エンジンの起動とメインループ

目次序文準備行く!文章プロセスを開始するメインループまとめ要約する序文準備皆さんは、こんなことを考え...

CSS3はブラウザのスクロールバーのスタイルを変更します

注意: この方法は、Webkit ベースのブラウザにのみ適用されます。ブラウザのスクロールバーが広す...

ElementUIはel-formフォームリセット機能ボタンを実装します

目次ビジネスシナリオ:効果のデモンストレーション:ビジネスシナリオ: el-form を使用する場合...

MySQLクエリ速度を最適化する方法

前の章では、高性能な MySQL に不可欠な、最適化されたデータ型の選択方法とインデックスの効率的な...

Nginx サーバーの https 設定方法の例

Linux: Linux バージョン 3.10.0-123.9.3.el7.x86_64 ngin...

MySQL 8.0 における MySQL のインストールと新しいパスワード認証方法の詳細な説明

1. はじめにOracle が MySQL 8.0GA をリリースしました。海外での GA はリリー...

Vueはユーザーログイン切り替えを実装します

この記事では、ユーザーのログイン切り替えを実現するためのVueの具体的なコードを例として紹介します。...

Linux での MySQL のインストールに関する詳細なチュートリアル

1. MySQLサービスをシャットダウンする# service mysqld stop 2. rpm...