最も左のプレフィックス原則とMySQL [インデックス]インデックスのプッシュダウン最適化

ディレクトリ

まず、の導入

第二に、カバレッジインデックス

基盤となるストレージアーキテクチャの次の共同インデックスの話をする前に問題について話をする最初のように見えますか?共同インデックス検索処理は、どのようなことでしょうか?

第三に、最も左のプレフィックスの原則

最も左のプレフィックス定義された原則

第四に、インデックスプッシュダウン

V.の概要


まず、の導入

この記事を開始する前に、まず明確なコンセプトの、クラスタ化インデックスの各ノードは、B +ツリーのあるインデックス・ページ、インデックス・ページには、以前の正常なのの規定に基づいて行われますプットのどのように多くのインデックスページのインデックス値を決定します。

 

唯一の非リーフノードのインデックス領域(インデックスエントリのみ索引データを格納する、です)。

リーフノードとインデックス領域を有するデータ領域(データ項目)を、インデックスは、インデックスデータ記憶領域である主キーインデックスのデータ領域と二次インデックスツリーツリーは異なっています。

  • InnoDBの主キーテーブルインデックスツリーのリーフノードは、テーブル全体のデータのデータ領域に格納されます。
  • InnoDB テーブルのセカンダリインデックスツリーのリーフノードは、ノードに対応する主キーインデックスに格納されます。

 

ノードB +の数ができることを確認することは容易である冗長この冗長性は影響を受けないように、格納されたインデックス値を、しかし理由少ないデータ量の指標によって占め。

 

ここでは、この質問を見て:

次の表Tには、私は3と5の間でkは、あなたが走査線検索操作の数倍の木、どのくらいの意志を実行する必要がT SELECT * FROMを実行する場合は?

 

以下は、初期化ステートメントの表です。

mysql> create table T (
ID int primary key,
k int NOT NULL DEFAULT 0, 
s varchar(16) NOT NULL DEFAULT '',
index k(k))
engine=InnoDB;

insert into T values(100,1,'aa'),(200,2,'bb'),(300,3,'cc'),(500,5,'ee'),(600,6,'ff'),(700,7,'gg');

 

InnoDBのインデックス組織構造

现在,我们一起来看看这条 SQL 查询语句的执行流程:

  1. ID = 300を取得し、K = 3は、インデックスツリーkのレコードを検索します。
  2. 次に、インデックスツリーIDがIDに対応= 300がR3を発見しました。
  3. ID = 500を得るために、kの値k = 5にインデックスツリーを削除します。
  4. バックIDに対応するインデックスツリーIDへ= R4 500を発見しました。
  5. K値k = 6におけるインデックスツリーを削除し、条件が、ループの端部を満たしません。

 

因为B+树的叶子节点之间都按循序用指针连接在一起,所以k的索引树找到3的叶子节点之后直接根据叶子节点的后继指针到5结点就行了,依次同理,什么时候结点的索引值k不符合查询条件中的范围要求了就结束查询。

 

在这个过程中,回到主键索引树搜索的过程,我们称为回表。可以看到,这个查询过程读了 k 索引树的 3 条记录(步骤 1、3 和 5),回表了两次(步骤 2 和 4)。

 

在这个例子中,由于查询结果所需要的数据只在主键索引上有,所以不得不回表。那么,有没有可能经过索引优化,避免回表过程呢?这里就引入了覆盖索引的概念。

 

第二に、カバレッジインデックス

ステートメント3との間のK Tから選択IDを実行した場合と5は、 その後だけIDの値をチェックする必要があり、ツリー内のインデックスkのID値は、ノードのデータ領域を有している(二次インデックスツリーが格納された対応します主キーの値)は、それはあなたが必要としない、直接クエリ結果を提供することができますバックテーブルへ言い換えれば、このクエリの内部は、インデックスkは、私たちの調査の必要性は、私たちは、いわゆる「カバー」されているカバーするインデックスを

 

カバーインデックスは、ツリーの検索数を減らすことができるので、大幅ので、カバーインデックスは一般的なパフォーマンス最適化ツールで使用し、クエリのパフォーマンスを向上させます。

 

インデックスkにインデックスを使用したエンジンカバーの内部には、実際に3つのレコードを読み、そのノートは、R3〜R5(対応するインデックスk上のエントリ)が、MySQLサーバー層のために、エンジンを取るために探しています二つのレコードに、そのスキャンラインの数は、MySQLの2見なされます。

 

上記の説明に基づいてインデックスをカバーし、我々は問題を議論:公開情報シートには、ID番号との名前かどうかを確立する必要があるの関節指数(インデックスは、インデックスの作成をカバーし、関節を作成する方法ですか)

 

次のように公共のテーブルのこの定義があると仮定すると:

CREATE TABLE `tuser` (
  `id` int(11) NOT NULL,
  `id_card` varchar(32) DEFAULT NULL,
  `name` varchar(32) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `ismale` tinyint(1) DEFAULT NULL,
  PRIMARY KEY (`id`), -- 这个表的主键是单独建了一个id,不是用的身份证号,因为身份证号太长了,用它作为主键太占空间
  KEY `id_card` (`id_card`),
  KEY `name_age` (`name`,`age`)
) ENGINE=InnoDB

 

私たちは、ID番号が公共の一意の識別子であることを知っています。公共の情報ニーズに応じて、クエリID番号がある場合はつまり、限り、我々はID番号フィールドにインデックスを構築するとして、(十分にあるので、ちょうど最初に対応したID番号が主キー索引ツリーにID番号に対応する見つける必要があるID 、その後、主キーを見つけるために主キーのインデックスからツリーの下のID だけに、適切な居住者の情報を見つけるためにB + のクエリ数の二倍を行うこと)。再確立の関節指数の(ID番号、名前)のみ、あなたがインデックスに対応するインデックスエントリを見つけるために必要なデータを見つけることができ、クエリを構築する必要があり、このインデックスは、テーブルの主キーインデックスクエリに戻ってきていません木は)各ビルドインデックスは、あなたがB +ツリーを作成する必要があり、対応するデータが内部に格納されているため)、(スペースの無駄ではないでしょうか?

 

 公共のID番号から彼の名前を照会するための高周波要求は、今がある場合は、への共同指数は理にかなっています。これは、高周波要求に使用することができますインデックスをカバーする(インデックスフィールド内のインデックスエントリが照会される分野をカバーし、インデックスによって覆われている)セカンダリインデックスツリーに直接ID番号に応じて自分の名前を確認することができるようにするので、 、ないリーフノードのデータ領域は、依然として主キー記憶装置に対応するその助剤であるが、ストレージノードのインデックス領域に良好な(ID番号+名)関節インデックスを作成することであり、それはインデックス領域から直接必要なデータを得ることができるがその後、我々は、全体のラインの記録を確認する文の実行時間を短縮するために、テーブルに戻る必要があります。

 

もちろん、インデックスフィールドを維持すること(詳細を参照常に価格です索引メンテナンスを)。したがって、被覆インデックスをサポートするために、冗長なインデックスを作成するときのトレードオフを考慮する必要があります。これは、ビジネスのDBA(データベース管理者)である、またはビジネスデータアーキテクトの仕事として。

 

 

 基盤となるストレージアーキテクチャの次の共同インデックスの話をする前に問題について話をする最初のように見えますか?共同インデックス検索処理は、どのようなことでしょうか?

インデックスフィールドの複数の図において上記のように複数のフィールドは、すべてのノードのインデックス領域にインデックスの順に定義する場合、B +ツリーを構築するために組み合わせます。左から右への複数のフィールドは、(マップビュー上の上から下に比較したものである)の比較があるときの比較インデックスツリーインデックスを行って検索します。

 

3つの方法でサンプルクエリプロセスとして上図:

  1. 最初のフィールドデータと検索インデックスフィールドは同じではありません
  2. データ検索インデックスフィールドと同一の第一フィールド
  3. データ検索インデックスフィールドの最初の2つのフィールドと同様

 

  • 状況:それはデータページに右に直接であるので、データが検索される条件(10003、XXX、XXX)、発見を取得するために、ルートから始めるが10002より大きく、10004、右を見つけるには、それがあるよりも比較的小さく、 、インデックスの背後にある二つのフィールドを比較する必要はありません
  • ケース2:データの条件が検索される(10001、Assiatant)は、プロセスの場合と同様に、データ・ページの左側にある最初の完全なインデックスと比較して、フィールドに直接移動し、第1フィールドと、クエリデータを見つけます最初のフィールドデータの左ページの3つのノードが同じで、それは、第2のフィールドを比較することになる、インデックス領域は3つのフィールドがあるが、それは直接、このノードであるように、最も左のノードことを見出し、しかし、唯一の2つの検索フィールド、そして3番目のフィールドを制御し、これは直接フィールドではありません。これは、この場合の原理についての最も左のプレフィックス実行話は最も左のプレフィックスの原則です
  • 三つの場合:条件データが取得される(10003、スタッフ、XXX)は、この場合は、完全なFOUNDは、第二のケースに応じて第2のフィールドを比較し、データ・ページへ右に、第1の比較の場合に応じて終了します同じであるが、データ検索の分野は、第3領域インデックスフィールドを比較します
  • 追加の状況:データが条件は(10003)であれば、その後、彼は右のページにデータを取得するための手順の場合に従いますし、その後、すべてのノードの最初のインデックスページの右側のデータフィールドを見つける検索するので、10003です2つのノードに直接1つだけ検索フィールド(10003)は、全ての権利データページを取得します。これは、アプリケーションの最も左のプレフィックスの原則であります

 

第三に、最も左のプレフィックスの原則

ここでは、各クエリのインデックスをデザインする場合は、疑いがあると表示され、インデックスはあまりありません。私は彼の自宅の住所を確認するために、公共の識別番号をフォローしたい場合は?ビジネスでの需要のこのクエリの確率は高くありませんが、我々はそれが正しい、全表スキャンを手放すことができませんか?逆に、インデックスの作成別々の(ID番号、アドレス)が頻繁に要求ではなく、無駄を少し感じどのように私はそれを行う必要がありますか?

 

ここでは、私はあなたにあなたの結論を言ってみましょう。このB +ツリーインデックス構造インデックスは、レコードを検索するために、「一番左の接頭辞」に使用することができます。

 

視覚的にこの概念を説明するために、我々は分析するために(名前、年齢)この共同インデックスを使用しています。

(名前、年齢)インデックス概略図

これは、索引エントリが内部定義されたインデックスフィールドに合わせて出現順にソートされ、見ることができます。

 

ニーズがで発見された場合、すべての論理名は、迅速ID4に移動することができ、その後、反復後方には、あなたが望むすべての結果を取得するには、「ジョー・スミス」です。

 

あなたが最初の単語のすべての名前を確認したい場合は、「張」の人、あなたのSQL文の条件がされている「ここで、 『張%』のような名前。」条件が満たされていないまで、この時点で、あなたはその後、反復後方、最初に一致したレコードがID3で見つけ、インデックスを過ごすことができます。

 

 これらは、検索を高速化するための最も左のプレフィックスの原則の原則です。数が少ないようなインデックスツリーのインデックスエントリは唯一の座席であれば、それは直接的に作られたので、単に、「ジョン・ドウ」の検索などの項目を、取得するためのインデックスエントリの数を超える場合検索の最も左のプレフィックスの原則のすべてが、このようなものですジョー・スミスはノード。あなたがより多くのノードの着座後、ノードは、複数のリターンを取るしている場合は、インデックスの木が順序付けられているので、(このプロセスは、最初のノードジョー・スミスを見つけることですし、他のノードジョー・スミスはまた、順番に保存されています次のノードは、直接右へのアクセスノード・トラバーサル)は、これまでの条件を満たさなくなるまで、再びライン上の一つの表1に。

 

最も左のプレフィックスに定義原則:

それは限り最も左接頭辞として、あなたは、検索を高速化するためにインデックスを使用することができ、インデックスだけでなくすべての定義を見ることができます。最も左接頭辞をすることができ、関節指数 Nフィールド左端の、それもすることができ、文字列のインデックス Mの文字左端。Nは(このNフィールドが、あまり起こらないあなたはNフィールドの共同インデックスを含む左端でクエリするフィールドことを、彼らは同じを持っているため)、その後、必要のない犯罪者Nを別のインデックスを作成するには、チェコのフィールド、既存の共同インデックスを直接使用することは、あなたは同じ効果を再生することができますすることができます。

 

最も左のプレフィックスの原則に沿ったものではなく、試合の左端の文字、「%23」、としてこの使用では、それはインデックスを使用することはできません、このインデックスはトラバースには何も、私たちの唯一の1を取るされていない、なぜならインデックスの比較はから、開始するには、左から右にしているかの百分の一、それはインデックスを使用することはできませんので、それを比較する方法はありませんと、このスタート。

 

しかし、いくつかの例では、上記の場合のように、それは非常に便利です

例:表のURLのURLに保存されています

www.baidu.com

www.360.com

www.null.xyz

私は今、XYZドメイン名サフィックスを探しています、あなたは「%COM」クエリのように見える必要があるが、それは不可能非常に遅いにつながることができ、インデックスクエリを使用することができます

 

このソリューションは、ドメインデータを挿入し、後方であります

moc.udiab.www

このクエリは、「COM%」であるときは、そのデータベースを使用する際にちょっとしたトリックであるインデックスを、使用することができます。

 

:インデックスの最も左のプレフィックスの面の指示に基づいて、我々はこの問題について議論インデックスのフィールドの順序をアレンジする方法を、共同インデックスの設立を

 

私たちの評価基準をここでは、インデックス多重化機能それが最も左接頭辞、そうだwhen've(a、b)は共同インデックスをサポートできるため、一般的に別のインデックスを必要としません。したがって、第一の原則は、順序を調整することで、あなたは低いインデックスを維持することができれば、その優先順位が頻繁に使用されていることです

 

 だから今、あなたが知っている、このセクションの冒頭の質問は、私たちは、高周波要求(ID番号、名前)の共同インデックスを作成する「ID番号の問い合わせアドレスに応じて、」需要のニーズが高頻度ではない、私たちはしませんでした関節指数の(ID番号、アドレス)を維持するために必要。そして、あなたはアドレスに基づいて、検索クエリの速度ID番号を改善したい場合は、あなたが必要(ID番号)を持ち、インデックス、または他のMySQLは、コンテンツを照会するために全体のB +ツリーを走査します。そして、我々は、インデックスが直接インデックスを使用して、その原則によると、最も左のプレフィックスの原則は、便利な、することができます(ID番号、名前)高周波電力学校(ID番号)として機能するように要求との共同インデックスに来ることができてい共同インデックスによってオンデマンド(「ID番号の問い合わせアドレスに応じた」サポートが迅速だけ迅速主キーインデックスツリーから主キーIDに対応するリーフノードを見つけるには、主キーのIDに対応するID番号を見つけた、彼はすべてのIDを見つけることができます)のアドレスデータを含みます。

 

だから、共同問い合わせの両方の場合、またお問い合わせの、Bそれぞれのフィールドに基づいてすることはありますか?Bのみステートメントが最も左接頭辞の原理と一致しない(a、b)はジョイントインデックスを使用することができないクエリ。この時間は、あなたが(a、b)は、(b)は、2つのインデックスを維持する必要がある手段、別のインデックスを維持する必要があります。

 

この時点で、我々は望ん原則配慮がスペースであるの。例えば、上記の状況公共のテーブルには、名前フィールドは、フィールドの年齢よりも大きい場合、その後、私はあなたが共同インデックスとの単一フィールドインデックス(年齢)の(名前、年齢)を作成することを示唆しています。効果は同じですが、後者の名前は、二つの大きな分野、より多くのスペースに格納されているが、(年齢、名前)のジョイントインデックスと(名前)のインデックスを確立しないでください。

 

 

第四に、インデックスプッシュダウン

私たちは最も左のプレフィックスの原則を満たす期間といえば、最も左のプレフィックスは、インデックス内のレコードを検索するために使用することができます。この時点で、あなたはそれらの部品は、左端の接頭辞を満たしていない、お聞きしたいことがあり、何が起こるのだろうか?

 

私たちは、例えば、まだ公共の共同インデックステーブル(名前、年齢)のメンバーでした。需要今がある場合:テーブルを取得するには、「最初の言葉は、10歳の張、およびすべての男の子の名前です。」だから、SQL文はそう書かれています:

mysql> select * from tuser where name like '张%' and age=10 and ismale=1;

 

あなたはすでに、ルールの接頭辞インデックスを知っている唯一の「張」のレコードは、ID3は、最初の条件を満たして見つかった検索インデックスツリー内のこの文そう。もちろん、これは、全表スキャンが優れているよりも優れ、また良いです。

 

然后呢?当然是判断其他条件是否满足。

 

在 MySQL 5.6 之前,只能从 ID3 开始一个个回表。到主键索引上找出数据行,再对比字段值。而 MySQL 5.6 引入的索引下推优化(index condition pushdown), 可以在索引遍历过程中,对索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数。

 

图1和图2,是这两个过程的执行流程图。

1ノー実行フローインデックスマッププッシュダウン

 

図2のインデックスは、実装プロセスを押し下げ

図1及び図2において、各点線の矢印内の2一度テーブルに戻って示します。

图 1 中,在 (name,age) 索引里面我特意去掉了 age 的值,这个过程 InnoDB 并不会去看 age 的值,只是按顺序把“name 第一个字是’张’”的记录一条条取出来回表。因此,需要回表 4 次。

图 2 跟图 1 的区别是,InnoDB 在 (name,age) 索引内部就判断了 age 是否等于 10,对于不等于 10 的记录,直接判断并跳过。在我们的这个例子中,只需要对 ID4、ID5 这两条记录回表取数据判断,就只需要回表 2 次。

 

V.の概要

今日は、あなたと私は、インデックスをカバーするなど、プリフィックス索引をデータベースインデックスの概念を議論し続けるこの記事では、インデックスが押し下げ。あなたが見ることができるように、リソースへのアクセスはほとんどとして、文のニーズを満たしながら、データベース設計の重要な原則の一つです。我々はターゲットとして特に設計テーブル構造では、データベースを使用するだけでなく、資源の消費を削減する場合には


その他の関連記事:[MySQLの] MySQLストレージエンジンおよびインデックスコメント(クラスタ化インデックスと非クラスタ化インデックス)
                        [MySQLの] InnoDBの行フォーマット、データページの構造と原理分析の基礎となる指標
                        【のMySQL] InnoDBストレージエンジン、MyISAMストレージエンジン、クラスタ化インデックス非クラスタ化インデックス、主キーインデックス、セカンダリインデックスとの間にカーディング関係
                        【のMySQL]のInnoDBインデックスモデル(B +ツリー)
                        【のMySQL] MySQLのロックトランザクション分離レベルの説明
                        【のMySQL] MySQLのサブライブラリーサブテーブルの説明
                        [MySQLの]詳細なマスタースレーブレプリケーションの実装の原則


参考:「MySQLの戦闘45のストレス」林Xiaobin

公開された54元の記事 ウォン称賛47 ビュー10000 +

おすすめ

転載: blog.csdn.net/cy973071263/article/details/104550117