B+ ツリー インデックスのリターン テーブルのコスト (10)

一緒に創造し、成長するために一緒に働きましょう!「ナゲッツデイリー新プラン・8月アップデートチャレンジ」参加27日目、イベント詳細はこちら

B+ ツリー インデックスのリターン テーブルのコスト (10)

序文

返品フォームとは

通常、テーブルを返す操作はセカンダリ インデックスで行われ、クエリ列がすべてセカンダリ インデックスに含まれているわけではありません.セカンダリ インデックスのリーフ ノードのプライマリ キー ID に従って、クラスター化インデックスの完全なユーザー データをクエリする必要があります. index. このクエリ プロセスは、return テーブルと呼ばれます。

テストテーブル person_info がある場合

CREATE TABLE person_info(
    id INT NOT NULL auto_increment,
    name VARCHAR(100) NOT NULL,
    birthday DATE NOT NULL,
    phone_number CHAR(11) NOT NULL,
    country varchar(100) NOT NULL,
    PRIMARY KEY (id),
    KEY idx_name_birthday_phone_number (name, birthday, phone_number)
);
复制代码

同時に、セカンダリ インデックスは複合インデックスとも呼ばれます。idx_name_birthday_phone_number データ インデックスの構造は次のとおりです。

image-20220823193512122.png

次の SQL がある場合、B+ リーフ ノードには name、birthday、phone_number、id が含まれますが、country 列は含まれません。

select country,name,birthday from person_info limit 10;
复制代码

name 列と birthday 列は、結合インデックス idx_name_birthday_phone_number のリーフ ノードを介して直接取得でき、主キー id から主キー インデックス ツリーに国を取得する必要があります. 国列情報を取得するプロセスは、return と呼ばれます。テーブル。

返品費用

別の例は、次の SQL です。

select * from person_info where name > 'Asa' and name < 'Barlow';
复制代码

クエリ列はすべて sql であるため、テーブルに戻す必要があることは明らかですが、ここではランダム IO とシーケンシャル IO の 2 つの概念について言及する必要があります。

複合インデックス idx_name_birthday_phone_number があるので名前順に並び、name > 'Asa' かつ name < 'Barlow' の条件により、真ん中のデータを取る確率は連続したスペースになるので、 1 つまたは複数のデータ ページ データ ページはデータをすばやく取得できます。ディスク データを読み取るこのプロセスは、シーケンシャル IOと呼ばれます。

セカンダリ インデックスには国列が含まれていないため、名前 > 'Asa' および名前 < 'Barlow' の範囲内のすべてのレコード ID に基づいて、非クラスター化インデックスで完全なレコードを再度クエリする必要があり、ID はランダムである可能性があります異なるデータページに割り当てられている場合、クエリの難易度は名前列の値のクエリよりもはるかに高く、この読み取り方法はランダム IOと呼ばれます。

ほとんどの場合、シーケンシャル IO のパフォーマンスはランダム IO よりもはるかに高くなります。

したがって、分析手順に従って、複合インデックス クエリを使用すると、2 つの特徴を得ることができます。

  • クエリは 2 つのインデックスを使用します。1 つは複合インデックスで、もう 1 つはクラスター化インデックスです。

  • 通常、シーケンシャル IO は複合インデックスへのアクセスに使用され、ランダム IO は通常、クラスター化インデックスへのアクセスに使用されます。

つまり、テーブルに返されるデータの量が多いほど、複合インデックスの使用効率が低下します. **name > 'Asa' および name < 'Barlow'** の範囲のデータがより多くを占める場合.テーブル データ全体の 90% を超える場合は、フル テーブル スキャンを使用する方が適切です。次に、いつフル テーブル スキャンを使用し、いつインデックス クエリを使用しますか? これはオプティマイザーに依存し、オプティマイザーはテーブルに返されるレコードの数を参照します。

したがって、上記の SQL を次のように記述すると、

select * from person_info where name > 'Asa' and name < 'Barlow' limit 10;
复制代码

テーブル リターンの数を減らすと、自然なオプティマイザーは、セカンダリ インデックス (複合インデックス) + テーブル リターンの操作に傾倒します。

バックフォームの回避方法

テーブルに戻るコストを知っているので、それを回避する方法を知る必要があります.テーブルに戻るという前の分析の理由は、クエリ列がインデックス列の間に完全に存在しないためです.主キー ID に基づくクラスタ化インデックス この理由によると、インデックス カバレッジを使用してこの問題を解決できます

以下のように、上限制限はありませんが、複合インデックス idx_name_birthday_phone_number にはクエリのすべての列が含まれているため、再度テーブルに戻ることなく目的を達成できます。

select name, birthday, phone_number from person_info 
where name > 'Asa' and name < 'Barlow';
复制代码

上記の分析を通じて、クエリ列が複合インデックスのクエリに影響を与えることがわかっているため、 **select ** のような構文を使用しないようにし、クエリ列を明示的に指定する必要があります。

おすすめ

転載: juejin.im/post/7136202381334675486