この単純なSQLは、どのようにインデックスを追加するには?知識の私の年を覆します

オリジナル:妹味(マイクロチャネル公共番号ID:xjjdog)、共有してくださいは、ソースを保管してください再現しました。

ナゲッツ多能性ヒト原則コンテンツは、メッセージを残すことができます。

直接トピックに、長ったらしいません。問題は、このです。次のSQL文は、クエリをスピードアップするためには、どのようにインデックスを作成するのでしょうか?以下は、mysqlデータベースが優先する。

select * from test where a=? and b>? order by c limit 0,100
复制代码

結果はあなたを驚かせるかもしれません。私たちは、最初の準備動作環境を見て、最も左のプレフィックスの原則に基づいて、認証用の鍵を説明します。結果は本当に認知xjjdog年覆します。

準備フェーズ

検証のために、我々は簡単なスプレッドシートを作成しました。3つの簡単なint型フィールドC、Bがあります。

CREATE TABLE `test` (
  `id` int(11) NOT NULL,
  `a` int(11) DEFAULT NULL,
  `b` int(11) DEFAULT NULL,
  `c` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
复制代码

次に、データの10ワットを挿入するために、単純なストアドプロシージャを記述します。約1分、完全に挿入されたデータを待ちます。

DROP PROCEDURE IF EXISTS test_initData;
DELIMITER $
CREATE PROCEDURE test_initData()
BEGIN
    DECLARE i INT DEFAULT 1;
    WHILE i<=100000 DO
        INSERT INTO test(id,a,b,c) VALUES(i,i*2,i*3,i*4);
        SET i = i+1;
    END WHILE;
END $
CALL test_initData();
复制代码

MySQLは最も左接頭原理を持っているので、私たちはABCの3は、完全な配列だった、6つのインデックスを作成しました。このインデックスは、ABCに基づいてすべてのクエリの6をカバーしています。

create INDEX idx_a_b_c on test(a,b,c);
create INDEX idx_a_c_b on test(a,c,b);
create INDEX idx_b_a_c on test(b,a,c);
create INDEX idx_b_c_a on test(b,c,a);
create INDEX idx_c_a_b on test(c,a,b);
create INDEX idx_c_b_a on test(c,b,a);
复制代码

認証に使用する説明

1、インデックスの自動選択

 explain select * from test where a>10 and b >10  order by c
复制代码

まず、検証上記のSQL文を取ります。それは、それがインデックスを使用して発見されたidx_a_b_c、唯一のB、接頭辞aを使用しました。余分な部分は、filesortレコードを使用し、パフォーマンスが非常に悪い方法です。

私たちは、私の立場クエリパラメータを変更しようとしました。

 explain select * from test where c>10 and b >10   order by a
复制代码

インデックスが自動的に選択され idx_b_a_c ますが、filesortレコードがまだ使用され、効果は同じクエリです。上記のロジックによると、あなたはそれidx_b_c_a選ぶべきではないのですか?

2、指定されたインデックス

次に、力指数を使用し、指定されたインデックスを余儀なくされました。ここで与えられている直接の結果は、次のSQLです。

 explain select * from test 
    FORCE INDEX(idx_c_b_a)
    where a>10 and b >10  order by c
复制代码

結果は以下の通りです。

我々は、使用するインデックスを指定するために力指数を使用しています。効果はどこ、インデックスのみの操作を完了するために使用して、インデックスの使用を示す、非常に良いです。しかし、走査線の数が増加しています。

しかし、これは私たちの経験に反しています。idx_c_b_aインデックスはフィールド上で作成された(C、B、A)。C、CB、CBA:検索条件の最も左側の原理サポートによります。この例では、バックのパラメータによって注文が、プレフィックスヘッダ情報として使用しました。

私たちはidx_c_b_a、そして力指数部分を削除したまま、他のインデックスを削除します。これは、MySQLは自動的にインデックスを選択することができ、発見されました。

別、順番を見た場合の2つのパラメータがあります。

 explain select * from test 
    FORCE INDEX(idx_b_c_a) 
    where a>10   order by b,c
复制代码

その結果、idx_b_c_aの使用は、filesortレコードを行っていません。その他のインデックスは最適ではありません。

3、戻り値の意味の一部を説明

私たちは自分自身を提供するために、MySQLのツールを説明するためによると、上記の結論に来ます。このツールは、出力いくつかの有用な情報をすることができます。ここでは、戻り値の関連部分の意味があります。

SELECT_TYPE
SELECTタイプを表す、一般的な値は次のとおりです。

SIMPLEテーブルを使用することなく、簡単な表では、結合またはサブクエリ。
PRIMARYメインクエリ、すなわち外部クエリ。
UNION第二またはクエリの後ろにUNION。
SUBQUERY最初のサブクエリ。

タイプは、
MySQLがテーブルに所望のモード行を見つける、またはアクセスタイプを呼び出す表します。下から一番上に、次のように一般的なアクセスタイプは、パフォーマンスが悪化しているされています。

system,constカラムCONSTの特殊なタイプでのみ1つの行テーブル(システムに等しいテーブル)。
eq_refユニークなインデックス・スキャンは、各インデックスキーのために、テーブルには一つだけ、一致するレコードです。
ref非ユニークインデックス・スキャンは本質的に、単一の値に一致するすべての行を返すインデックスアクセスの一種である、単一の値に一致するすべての行を返し、しかし、ラインの条件に沿ってより多くのそれを見つけたので、彼もそれは、検索とスキャンの混合物に属している必要があります。
range行インデックスが使用されるキー列の番組を選択するためにインデックスを使用して、唯一のライン所定の範囲に取り出します。それが唯一のインデックスは、別のポイントで終了し、ある時点で開始する必要があるため、この索引レンジ・スキャンは、全表スキャンよりも優れている、インデックス全体をスキャンする必要はありません。
index全索引スキャン、インデックスおよびすべての屈折率の差は、インデックスツリーのみを横断するタイプです。インデックスファイルはデータファイルよりも通常小さいので、これは、ALLよりも通常は高速です。
all全表スキャン、最悪のパフォーマンス

余分な
using index
テーブルのデータ行へのアクセスを回避するように選択指標被覆、良好な効率に対応する指示操作。同時に、インデックスが検索インデックスキー値を実行するために使用されていることを示していない場合に使用してある場合は、何も同時にここで使用している場合は、インデックスがデータを読み取るのではなく、ルックアップ動作を実行するために使用されることを示しています。

using filesort
MySQLは代わりに、テーブルのインデックス順の読み出し、外部データの順序インデックスを用いて説明します。MySQLは、ソート操作が呼び出される完了するために、インデックスを使用することはできません「ファイルをソートします。」

using temporary
クエリ結果をソートするときに使用するmysqlの一時テーブル、中間結果を保持するために一時テーブルを使用してください。でクエリグループをソートし、グループ化することで順番に共通します。

終わり

最適な方法で使用されるMySQLのクエリの最適化、および必ずしも知的な解析が、力インデックス指定されたインデックスを使用する必要があるときは、私たちが作成した複数のインデックスを見ることができます。

MySQLのインデックスは、それが主に条件とソート操作に使用されます。二つのケース。

図1は、第一フィルタ、ソート、インデックスパラメータは、フィルタ条件に使用されるが、より遅い外部ソートを使用してソートされます。ので、結果セットを濾過し、そして何のインデックスの参加はありません。

図2に示すように、最初の並べ替え、次いで濾過し、フィルタの優先順位よりも高い優先順位、同じインデックスを使用することができます。行うにはこの事を置くために濾過しながら、適切なインデックスを選択します。しかし、走査線の数が増加します。

私は、MySQLが速い遅い最後にこれら2つのプロセスが、その後、直接最初のを選択するための最も一般的な方法の一つを選んだということを理解することはできない、と思います。でも、インデックス、多くの時間、直接ユンカイインチ **インデックスがより多くのを構築するには、間接的にMySQLへの害を及ぼすことがあります。**これは根深いの理由として、説明するために、関連のMySQLのソースコードを読むことを歓迎し、現象です。

このソートフィールドのコードは、常に良好な信号ではなく、変化しています。アカウントへのプログラムの安定性を考えると、私たちは、フィルタ条件の後にどこに結果セットを削減しようとするべきだと思います。この場合、(a、b)はジョイントインデックスを作成、多分である折衷方法。

著者について:妹味(xjjdog)、公衆に迂回プログラマの数を許可していません。インフラとLinuxをフォーカス。ディケイドアーキテクチャ、日百億流れ、あなたはあなたに別の味を与え、高い同時実行の世界を探検。私の個人的なマイクロチャネルxjjdog0、友人を追加し、さらに交流を歓迎します。

おすすめ

転載: juejin.im/post/5d6881d4f265da03ab426341