目次
インデックスの使用法 (その 1)
インデックスの効率を検証する
インデックスの使用原理を説明する前に、まずインデックスを検証して、インデックスを使用してデータ クエリのパフォーマンスを向上できるかどうかを確認しましょう。
デモンストレーション中、以前のテーブル tb_sku を引き続き使用し、このテーブルに 1,000 万件のレコードを準備しました。
このテーブルでは、id が主キーであり、主キー インデックスがありますが、他のフィールドにはインデックスが付けられていません。まず、レコードの 1 つをクエリして内部のフィールドを確認し、次の SQL を実行しましょう。
select * from tb_sku where id = 1\G;
-- \G使行列互换,展示得更加清晰
検索結果:
データが 1,000 万件ある場合でも、主キー ID にはインデックスが付けられているため、ID に基づくデータ クエリのパフォーマンスは依然として非常に高速であることがわかります。
次に、sn フィールドに基づいてクエリを実行し、次の SQL を実行します (sn フィールドにはインデックスが付けられません)。
SELECT * FROM tb_sku WHERE sn = '100000003145001';
検索結果:
sn フィールドに基づくクエリがデータを返し、その結果に20.78 秒かかったことがわかります。これは、sn にはインデックスがないため、クエリ効率が低くなります。
次に、sn フィールドのインデックスを作成し、インデックスを作成した後、再度 sn に基づいてクエリを実行し、クエリの消費時間を確認します。
インデックスを作成します。
create index idx_sku_sn on tb_sku(sn);
テーブルには大量のデータがあり、B+Tree ツリーの構築に時間がかかるため、このインデックスの作成プロセスには時間がかかることがあります。
このインデックスを作成した後、同じ SQL ステートメントを再度実行して、その所要時間を確認します。
SELECT * FROM tb_sku WHERE sn = '100000003145001'\G;
sn フィールドにインデックスが作成された後は、クエリのパフォーマンスが大幅に向上していることがわかります。インデックス作成の前後では、クエリ時間は桁違いに異なります。
左端のプレフィックスルール
複数の列にインデックスが付けられている場合 (結合インデックス)、一番左のプレフィックス ルールに従う必要があります。
左端のプレフィックス ルールは、クエリがインデックスの左端の列から開始され、インデックス内の列をスキップしないことを意味します。列がスキップされた場合、インデックスは部分的に無効になります (後続のフィールド インデックスは無効になります)。
たとえば、現在、tb_user テーブルに結合インデックスがあり、この結合インデックスには、職業、年齢、ステータスの順に 3 つのフィールドが含まれています。
一番左のプレフィックス ルールは、クエリを実行するときに、一番左の列、つまり職業が存在する必要があり、存在しない場合はすべてのインデックスが失敗することを意味します。また、列を途中でスキップすることはできません。スキップしないと、列の後ろにあるフィールド インデックスが無効になります。
例えば:
クエリを実行するときに、職業が存在し、年齢が存在せず、ステータスが存在する場合、現時点では職業インデックスのみが有効になります。
職業が存在せず、年齢が存在し、ステータスが存在する場合、現時点ではインデックスは使用されません。
注: 一番左のプレフィックス ルールは、クエリ条件が書き込まれる順序とは関係がなく、結合インデックスが作成される順序のみに関係します。
今すぐ、
explain select * from tb_user where
profession = '软件工程'
and age = 31
and status = '0';
-- 这两条SQL是一致的
explain select * from tb_user where
age = 31
and status = '0'
and profession = '软件工程';
範囲クエリ
結合インデックスでは範囲クエリ(>,<)が発生し、範囲クエリの右側の列インデックスが無効になります。
例えば:
explain select * from tb_user where
profession = '软件工程'
and age > 30
and status = '0'; -- status在>之后,所以该列索引失效
したがって、職業と年齢フィールドのみがインデックス化されます。
ビジネスが許可する場合は、>= または <= のような範囲クエリをできるだけ使用し、> や < の使用は避けてください。
インデックスの失敗
-
インデックス列の操作
インデックス列に対して操作を実行しないでください。インデックスは無効になります。
たとえば、電話フィールドに対して関数操作を実行すると、そのインデックスは無効になります。
explain select * from tb_user where substring(phone,10,2) = '15';
-
引用符のない文字列
explain select * from tb_user where
profession = '软件工程'
and age = 31
and status = '0';
-- 没有加引号的话,status字段的索引就会失效
explain select * from tb_user where
profession = '软件工程'
and age = 31
and status = 0;
クエリ結果には影響しませんが、データベース内で暗黙的な型変換が行われるため、インデックスが無効になります。
-
ファジークエリ
末尾のあいまい一致のみがある場合、インデックスは無効になりません。ヘッダーあいまい一致の場合、インデックスは無効になります。
例えば:
explain select * from tb_user where profession like '软件%';
explain select * from tb_user where profession like '%工程'; -- 索引失效
explain select * from tb_user where profession like '%工%'; -- 索引失效
ファジークエリのような場合、キーワードの後に%を追加するとインデックスが有効になります。また、キーワードの前に%を付けるとインデックスが無効になります。
-
または接続条件
or で区切られた条件。 or の前の条件の列にインデックスがあるが、次の列にインデックスがない場合、関連するインデックスは使用されません。
たとえば、次の 2 つの SQL ステートメントは次のとおりです。
explain select * from tb_user where id = 10 or age = 23;
explain select * from tb_user where phone = '17799990017' or age = 23;
-- age没有索引,其作为联合索引也不满足最左前缀法则
ageにはインデックスがないため、idやphoneにインデックスがあっても無効となります。したがって、年齢に関するインデックスを作成する必要があります。
インデックスは、OR 接続の条件に左右のフィールドのインデックスが含まれている場合にのみ有効になります。
-
データ分散への影響
MySQL がインデックスの使用がテーブル全体よりも遅いと評価した場合、インデックスは使用されません。
MySQL はクエリを実行するときに、インデックスの使用効率とテーブル全体のスキャンの効率を評価し、テーブル全体のスキャンの方が速い場合は、インデックスを放棄してテーブル全体のスキャンを使用します。インデックスは少量のデータのインデックス付けに使用されるため、インデックス クエリを通じて大量のデータが返された場合、フル テーブル スキャンほど高速ではなく、インデックスは無効になります。
SQLプロンプト
SQL プロンプトはデータベースを最適化する重要な手段であり、簡単に言えば、操作を最適化するという目的を達成するために、SQL ステートメントに人為的なプロンプトを追加します。
MySQL が外部からクエリを実行するときに、使用できるインデックスが複数ある場合、MySQL は使用するインデックスを自動的に選択します。クエリ時にどのインデックスを使用するかを指定できますか? 答えは「はい」です。これは、MySQL の SQL プロンプトを使用して行うことができます。
次に、SQL プロンプトを紹介します。
-
インデックスを使用する
MySQL がこのクエリを完了するために使用するインデックスを推奨します (単なる提案です。mysql は内部で再度評価します)。
Explain select * from tb_user use Index(idx_user_pro)
where professional = 'ソフトウェア エンジニアリング';
-
インデックスを無視する
指定されたインデックスを無視します。
Explain select * from tb_user無視インデックス(idx_user_pro)
ここで、職業 = 「ソフトウェア エンジニアリング」;
-
フォースインデックス
インデックスの使用を強制します。
Explain select * from tb_user強制インデックス(idx_user_pro)
ここで、職業 = 「ソフトウェア エンジニアリング」;
終わり
学習内容: ダークホース プログラマー - MySQL データベース コース