MySql インデックスの詳細な紹介と正しい使用方法

MySql インデックスの詳細な紹介と正しい使用方法

MySql インデックスの詳細な紹介と正しい使用方法

1. はじめに:

インデックスはクエリ速度に重大な影響を与えるため、インデックスを理解することがデータベース パフォーマンス チューニングの出発点となります。

インデックスは、ストレージ エンジンがレコードをすばやく見つけるために使用するデータ構造です。データベース インデックスを適切に使用すると、システムのアクセス パフォーマンスが大幅に向上します。以下では、主に MySQL データベースのインデックスの種類と、より合理的で効率的なインデックス作成手法を作成する方法について説明します。

注: これは主に、InnoDB ストレージ エンジンの B+Tree インデックス データ構造を対象としています。

2. インデックスの利点

1. サーバーがスキャンする必要があるデータの量が大幅に削減され、データ取得速度が向上します。

2. サーバーがソートや一時テーブルを回避できるようにする

3. ランダムI/OをシーケンシャルI/Oに変換できる

3. インデックスの作成

3.1. 主キーインデックス

ALTER TABLE 'table_name' に PRIMARY KEY 'index_name' ('column') を追加します。

3.2 ユニークインデックス

ALTER TABLE 'テーブル名' ADD UNIQUE 'インデックス名' ('列');

3.3. 共通インデックス

ALTER TABLE 'テーブル名' ADD INDEX 'インデックス名' ('列');

3.4 全文索引

ALTER TABLE 'テーブル名' ADD FULLTEXT 'インデックス名' ('列');

3.5. 複合インデックス

ALTER TABLE 'table_name' ADD INDEX 'index_name' ('column1', 'column2', ...);

4. B+ツリーインデックスルール

テストユーザーテーブルを作成する

user_testが存在する場合はテーブルを削除します。
テーブルuser_testを作成します(
 id int AUTO_INCREMENT 主キー、
 ユーザー名varchar(30) NOT NULL、
 性別ビット(1) NOT NULL デフォルト b'1',
 都市varchar(50) NOT NULL,
 年齢 int NOT NULL
)ENGINE=InnoDB デフォルト文字セット=utf8;

複合インデックスを作成します: ALTER TABLE user_test ADD INDEX idx_user(user_name , city , age);

4.1. インデックス効果のあるクエリ

4.1.1、完全な値マッチング

完全な値一致とは、インデックス内のすべての列を一致させることを指します。たとえば、上記で作成したインデックスを例にとると、where 条件の後に、(user_name、city、age) を条件として同時にデータをクエリできます。

注: whereの後のクエリ条件の順序とは関係ありません。ここは多くの学生が誤解しがちなところです。

SELECT * FROM user_test WHERE user_name = 'feinik' AND age = 26 AND city = 'Guangzhou';

4.1.2. 左端の接頭辞に一致

左端のプレフィックスに一致するということは、最初に左端のインデックス列に一致することを意味します。たとえば、上記で作成したインデックスは、クエリ条件に使用できます: (user_name), (user_name, city), (user_name, city, age)

注: 左端のプレフィックス クエリ条件を満たす順序は、インデックス列の順序とは関係ありません (例: (city, user_name)、(age, city, user_name))。

4.1.3. 列プレフィックスの一致

一致する列値の先頭を参照します。例: ユーザー名が feinik で始まるすべてのユーザーをクエリします。

SELECT * FROM user_test WHERE user_name LIKE 'feinik%';

4.1.4、範囲値の一致

たとえば、ユーザー名が feinik で始まるすべてのユーザーを照会するには、ここではインデックスの最初の列が使用されます。

SELECT * FROM user_test WHERE user_name LIKE 'feinik%';

4.2 インデックスの制限

1. where クエリ条件にインデックス列の左端のインデックス列が含まれていない場合、次のようにインデックス クエリは使用できません。

SELECT * FROM user_test WHERE city = '広州';

または

user_test から * を選択 WHERE age= 26;

または

SELECT * FROM user_test WHERE city = 'Guangzhou' AND age = '26';

2. クエリ条件が左端のインデックス列であっても、ユーザー名がfeinikで終わるユーザーをクエリするためにインデックスを使用することはできません。

SELECT * FROM user_test WHERE user_name like '%feinik';

3. where クエリ条件に列の範囲クエリがある場合、その右側にあるすべての列ではインデックス最適化クエリを使用できません。次に例を示します。

SELECT * FROM user_test WHERE user_name = 'feinik' AND city LIKE 'Guangzhou%' AND age = 26;

5. 効率的なインデックス戦略

5.1. インデックス列は式の一部にしたり、関数パラメータとして使用したりすることはできません。そうしないと、インデックス クエリは使用できません。

SELECT * FROM user_test WHERE user_name = concat(user_name, 'fei');

5.2 プレフィックスインデックス

非常に長い文字列のインデックスを作成する必要がある場合もありますが、その場合、インデックスの保存スペースが増加し、インデックスの効率が低下します。1 つの戦略はハッシュ インデックスを使用することです。もう 1 つはプレフィックス インデックスを使用することです。プレフィックス インデックスは、文字列の最初の n 文字をインデックスとして選択するため、インデックス スペースを大幅に節約でき、インデックスの効率が向上します。

5.2.1. プレフィックスインデックスの選択性

プレフィックス インデックスは、高い選択性を確保できるほど長くする必要がありますが、長すぎてもいけません。適切なプレフィックス インデックスの選択長の値は、次のように計算できます。

(1)

SELECT COUNT(DISTINCT index_column)/COUNT(*) FROM table_name; -- index_columnはプレフィックスインデックスを追加する列を表します

注: プレフィックス インデックスの選択率は上記の方法で計算されます。比率が高いほど、インデックスの効率が高くなります。

(2)

選択

COUNT(DISTINCT LEFT(インデックス列,1))/COUNT(*),

COUNT(DISTINCT LEFT(インデックス列,2))/COUNT(*),

COUNT(DISTINCT LEFT(インデックス列,3))/COUNT(*)

...

テーブル名から;

注:上記のステートメントを使用すると、(1)のプレフィックスインデックスに最も近い選択率を徐々に見つけることができ、対応する文字切り捨て長を使用してプレフィックスインデックスを作成できます。

5.2.2. プレフィックスインデックスの作成

ALTER TABLE テーブル名 ADD INDEX インデックス名 (インデックス列(長さ));

5.2.3. プレフィックスインデックスの使用に関する注意

プレフィックス インデックスはインデックスを小さくして高速化する効果的な方法ですが、MySQL ではプレフィックス インデックスを ORDER BY および GROUP BY に使用したり、カバーリング スキャンに使用したりすることはできません。

5.3. 適切なインデックス列の順序を選択する

複合インデックスを作成する場合、インデックス列の順序は非常に重要です。正しいインデックス順序は、インデックスを使用するクエリ方法によって異なります。複合インデックスのインデックス順序は、経験則で決定できます。つまり、選択性が最も高い列をインデックスの先頭に配置します。このルールは、プレフィックス インデックスの選択性メソッドと一致しています。ただし、このルールを使用してすべての複合インデックスの順序を決定できるわけではありません。特定のインデックス順序も、特定のクエリ シナリオに応じて決定する必要があります。

5.4 クラスター化インデックスと非クラスター化インデックス

1. クラスター化インデックス

クラスター化インデックスは、物理ディスク上のデータの物理的な順序を決定します。テーブルには、クラスター化インデックスを 1 つだけ含めることができます。主キーが定義されている場合、InnoDB は主キーによってデータをクラスター化します。主キーが定義されていない場合、InnoDB は代わりに一意の空でないインデックスを選択します。一意の空でないインデックスがない場合、InnoDB は暗黙的に主キーをクラスター化インデックスとして定義します。

クラスター化インデックスはアクセス速度を大幅に向上させることができます。クラスター化インデックスはインデックスと行データを同じ B ツリーに格納するため、インデックスが見つかると、それに応じて対応する行データが見つかります。ただし、クラスター化インデックスを使用する場合は、ランダム クラスター化インデックス (一般に、主キーの値が不連続で、分布範囲が不均一であることを指します) を避けるように注意する必要があります。たとえば、UUID をクラスター化インデックスとして使用すると、UUID 値の不連続性により、インデックスの断片化やランダム I/O が大量に発生し、最終的にクエリのパフォーマンスが大幅に低下するため、パフォーマンスが非常に低下します。

2. 非クラスター化インデックス

クラスター化インデックスとは異なり、非クラスター化インデックスはディスク上のデータの物理的な順序を決定せず、インデックスは含まれますが、B ツリーの行データは含まれません。行データは、B ツリーに格納されているインデックスに対応するポインタによってのみポイントされます。たとえば、上記の (user_name, city, age) に作成されたインデックスは、非クラスター化インデックスです。

5.5 カバーインデックス

インデックス(複合インデックスなど)にクエリ対象となるすべてのフィールドの値が含まれている場合、そのインデックスはカバーリング インデックスと呼ばれます。

user_test から user_name、city、age を選択します。user_name = 'feinik' かつ age > 25 です。
クエリ対象のフィールド (user_name、city、age) はすべて複合インデックスのインデックス列に含まれているため、カバーリング インデックス クエリが使用されます。カバーリング インデックスが使用されているかどうかを確認するには、実行プランの Extra の値が Using index であるかどうかを確認します。これは、カバーリング インデックスが使用されていることを証明します。カバーリング インデックスを使用すると、アクセス パフォーマンスが大幅に向上します。

5.6 インデックスを使ってソートする方法

ソート操作において、インデックスを使用してソートすることができれば、ソート速度が大幅に向上します。インデックスを使用してソートするには、次の 2 つのポイントを満たす必要があります。

1. ORDER BY句の後の列の順序は複合インデックスの列の順序と一致している必要があり、すべてのソート列のソート方向(昇順/降順)は一致している必要があります。

2. クエリされたフィールド値はインデックス列に含まれ、カバーインデックスを満たす必要があります。

例を使って分析する

user_testテーブルに複合インデックスを作成する

ALTER TABLE user_test に ADD INDEX index_user(user_name, city, age);

インデックスソートが使用できる例

1. user_name、city、age を user_test から選択し、user_name で ORDER BY します。

2. user_test から user_name、city、age を選択し、user_name、city で ORDER BY します。

3. SELECT user_name, city, age FROM user_test ORDER BY user_name DESC, city DESC;

4. user_name、city、age を user_test から選択します。WHERE user_name = 'feinik' ORDER BY city;

注: ポイント 4 は少し特殊です。where クエリ条件がインデックス列の最初の列であり、定数条件である場合は、インデックスも使用できます。

インデックスソートが使用できない場合

1. 性別は索引欄にない

SELECT user_name, city, age FROM user_test ORDER BY user_name, sex;

2. ソート列の方向が一貫していない

SELECT user_name, city, age FROM user_test ORDER BY user_name ASC, city DESC;

3. クエリ対象のフィールド列性別がインデックス列に含まれていない

SELECT user_name、city、age、sex FROM user_test ORDER BY user_name;

4. whereクエリ条件の後のuser_nameは範囲クエリなので、インデックスの他の列は使用できません。

SELECT user_name, city, age FROM user_test WHERE user_name LIKE 'feinik%' ORDER BY city;

5. 複数のテーブルをクエリする場合、インデックス ソートは、ORDER BY 後のソート フィールドがすべて最初のテーブルのインデックス列である場合にのみ使用できます (上記のインデックス ソートの 2 つのルールを満たす必要があります)。たとえば、別のユーザー拡張テーブル user_test_ext を作成し、uid のインデックスを確立します。

user_test_ext が存在する場合はテーブルを削除します。

テーブルuser_test_extを作成します(

  id int AUTO_INCREMENT 主キー、

  uid int NOT NULL、

  u_password VARCHAR(64) NULLではない

)ENGINE=InnoDB デフォルト文字セット=utf8;

テーブル user_test_ext を変更し、インデックス index_user_ext(uid) を追加します。

インデックスで並べ替え

SELECT user_name, city, age FROM user_test u LEFT JOIN user_test_ext ue ON u.id = ue.uid ORDER BY u.user_name;

インデックスソートなし

SELECT user_name, city, age FROM user_test u LEFT JOIN user_test_ext ue ON u.id = ue.uid ORDER BY ue.uid;

6. まとめ

この記事では、主に B+Tree ツリー構造のインデックス作成ルール、さまざまなインデックスの作成、およびクエリ速度を最大化するための効率的なインデックス作成手法を正しく作成する方法について説明します。もちろん、インデックスの使用方法に関するヒントは他にもたくさんあります。インデックス作成についてさらに学ぶには、関連する経験を積む必要があります。

読んでいただきありがとうございます。お役に立てれば幸いです。このサイトをサポートしていただきありがとうございます。

以下もご興味があるかもしれません:
  • MySQL インデックスタイプの概要と使用上のヒントと注意事項
  • MySQLのINサブクエリによってインデックスが使用できなくなる問題を解決する
  • MySQLはインデックスを使用してクエリを最適化します
  • Mysql テーブル作成とインデックス使用仕様の詳細な説明
  • MySQL インデックスの正しい使い方とインデックスの原理の詳細な説明
  • MySQL インデックスの使用戦略と最適化 (高パフォーマンス インデックス戦略)
  • MySQLでインデックスを使用する方法を簡単に紹介します
  • MySQL でインプレースおよびオンライン メソッドを使用してインデックスを作成するチュートリアル
  • MySQL インデックスの使用方法 (単一列インデックスと複数列インデックス)
  • MySQL インデックス使用状況監視スキル (収集する価値あり!)

<<:  React Contextの理解と応用についてお話ししましょう

>>:  crontab でスケジュールされたタスクが実行されない理由の概要

推薦する

Element PlusはAffixを実装します

目次1. コンポーネントの紹介2. ソースコード分析2.1 テンプレート2.2 スクリプト2.3 実...

vue-cropperプラグインは、画像キャプチャとアップロードコンポーネントのカプセル化を実現します。

vue-cropperプラグインをベースにした画像キャプチャとアップロードコンポーネントをカプセル...

MySQL 数千万のビッグデータに対するSQLクエリ最適化の知識ポイントのまとめ

1. クエリを最適化するには、テーブル全体のスキャンを避けてください。まず、where と orde...

VMware 仮想マシンの 3 つのネットワーク方式と原則 (概要)

1. ブリッジ: デフォルトでは VMnet0 が使用されます1. 原則:ブリッジは、それぞれ 2...

フォーム OnSubmit と input type=image の使用の概要

ここに <input type="image"> がある場合、この画...

NodeJS は画像テキスト分割を実現します

この記事では、画像テキストセグメンテーションを実装するためのNodeJSの具体的なコードを参考までに...

Vue の匿名スロットと名前付きスロットの詳細な説明

目次1. 匿名スロット2. 名前付きスロット要約するスロット (slot) は、Vue のコンテンツ...

Web 開発 js 文字列連結プレースホルダーと conlose オブジェクト API の詳細な説明

目次プレースホルダーの置き換えコンソール印刷テーブル()ログ、情報、警告、エラーグループ()、グルー...

js タグ構文の使用法の詳細

目次1. ラベルステートメントの紹介2. ラベルステートメントの使用序文:日常の開発では、プログラム...

Mac Docker x509証明書の問題を解決する

質問最近、プライベートミラーセンターにログインする必要がありましたが、ログイン時にエラーメッセージが...

NginxはIP経由の直接アクセスを禁止し、カスタム500ページにリダイレクトします

設定ファイルに直接 サーバー{ listen 80 default; # IPへの直接アクセスを禁止...

Redis を Docker コンテナとして素早くデプロイする方法

目次はじめるデータストレージサーバーを構成するRedis セキュリティの管理Redisインストールの...

MySQL全文検索の使用例

目次1. 環境整備2. データの準備3. ショーを始める4. 単語分割エンジン要約する参考文献1. ...

nginx を介してローカルでリバースプロキシを構成するプロセス全体

序文Nginx は、イベント駆動型の非同期非ブロッキング処理フレームワークを使用する軽量 HTTP ...

CentOS 上の Docker に Jupyter をインストールしてポートを開く方法

目次jupyterをインストールするDocker ポートマッピングjupyterをインストールするp...