select文の最適化
- スローにするために
SELECT ... WHERE
、クエリ速く、最初に確認することは、あなたがインデックスを追加できるかどうかです。ディスクスペースを無駄にしないようにするには、構築複合インデックスを。 - 関数呼び出しを調整し、ファンクションコールは、大幅に向上させる効率が低下何倍です。
- 定期的に使用
ANALYZE TABLE
日までのテーブルの統計情報は、オプティマイザのための計画の効果的実施を構築するために必要な情報を提供します。 - 読んで
EXPLAIN
計画をしてインデックスを調整します。 - 大きさや性質のためのMySQLのキャッシュメモリ領域を調整します。
- ロックによって引き起こされたクエリパフォーマンスの問題を避けてください。
1. WHERE句の最適化
-
不要な括弧を削除します。
((a AND b) AND c OR (((a AND b) AND (c AND d)))) -> (a AND b AND c) OR (a AND b AND c AND d)
-
定数の折りたたみ。
(a<b AND b=c) AND a=5 -> b>5 AND b=c AND a=5
-
一定の条件が削除されます。
(b>=5 AND b=5) OR (b=6 AND 5=5) OR (b=7 AND 5=6) -> b=5 OR b=6
-
インデックスは一度だけ定数式を用いて算出されます。
-
直接からのMyISAMとMEMORYの無い(*)を持つ単一のテーブルの上にルックアップテーブルCOUNT。
-
無効な定数式。
SELECT * FROM t WHERE a<0 AND a>1; ︶︵︶
-
集約関数(例えばBYならないかGROUP
COUNT()
、MIN()
)、等)を有する句WHERE句に組み込まれます。SELECT * FROM t WHERE a=1 HAVING b>1; -> SELECT * FROM t WHERE a=1 AND b>1;
-
結合テーブルのそれぞれについて、構成簡素WHERE WHEREとすぐ行がスキップされるように、高速テーブルの評価としました。(複合WHEREデータの各ラインのためのフィルタ遅延時間)
-
クエリ内のすべてのテーブルでは、多くの場合、優先度のスケールをお読みください。定数テーブルは、次のいずれかになります。
-
空のテーブルまたは1つの行を含むテーブル。
-
インデックスの一部であるすべてが索引に句は、定数式と比較され、NOT NULLとして定義されているテーブルまたはPRIMARY KEY UNIQUEで使用するための、
以下の表はすべて定数テーブルとして使用されます。
SELECT * FROM t WHERE primary_key=1; SELECT * FROM t1,t2 WHERE t1.primary_key=1 AND t2.primary_key=t1.id;
-
-
場合
ORDER BY
とGROUP BY
同じテーブルからすべての列句を接続したときに、テーブルが優先されます。 -
ORDER BY
あるいは、GROUP BY
第一の接続表キュー以外のリストを含み、それが作成されます一時テーブルを(ソートされた接続データセットは自動的に削除ソートのため)。 -
すべての数字は、インデックス列にリストされている場合、MySQLはさえクエリデータファイルなしインデックスから行を読み取ることができます。
-
各列の出力前に、
HAVING
行IS句のものと一致しないスキップ。(結果セットのトリミングを行ったので、走査線の数を減少させません)
クイッククエリの例:
SELECT COUNT(*) FROM tbl_name;
SELECT MIN(key_part1),MAX(key_part1) FROM tbl_name;
SELECT MAX(key_part2) FROM tbl_name WHERE key_part1=constant;
SELECT ... FROM tbl_name ORDER BY key_part1,key_part2,... LIMIT 10;
SELECT ... FROM tbl_name ORDER BY key_part1 DESC, key_part2 DESC, ... LIMIT 10;
インデックス列が数値であると仮定すると、MySQLは次のクエリを解決するために、インデックスツリーのみを使用しています。
SELECT key_part1,key_part2 FROM tbl_name WHERE key_part1=val;
SELECT COUNT(*) FROM tbl_name
WHERE key_part1=val1 AND key_part2=val2;
SELECT key_part2 FROM tbl_name GROUP BY key_part1;
次のクエリは、別のソート横断せずにソートされた順序で行を取得するためにインデックスを使用しています。
SELECT ... FROM tbl_name
ORDER BY key_part1,key_part2,... ;
SELECT ... FROM tbl_name
ORDER BY key_part1 DESC, key_part2 DESC, ... ;
2.レンジオプティマイザ
BTREEとHASHインデックスの場合は、とき=、<=>、INは、NULL IS NULLまたはオペレータではありません
条件の範囲に対応する定数値の主要な要素との関係と比較します。
HASH
使用すると、インデックス=、<=>、IN()、 NULL IS、 またはNULL演算子されていない等価比較迅速。BTREE
索引使用>、<、> =、< =、BETWEEN ,! =、 または<>、LIKE「パターン」は重要な要素に対応する定数値との関係を比較、操作者(ここで、「パターン」はワイルドカードで始まらない)条件の範囲を。
最適化の試みから範囲WHERE
各可能なため句指標抽出範囲条件。抽出時、条件が条件の範囲を構築するために使用することができない削除、組み合わせ条件は、範囲の重複が発生し、空の範囲条件が発生除去します。最適化プロセスを参照のインデックスの単一部分の範囲のアクセス方法。
以上2.1比較値等間隔範囲の最適化
CREATE TABLE t1 (f1 INT NOT NULL, f2 INT NOT NULL, PRIMARY KEY(f1, f2));
INSERT INTO t1 VALUES
(1,1), (1,2), (1,3), (1,4), (1,5),
(2,1), (2,2), (2,3), (2,4), (2,5);
INSERT INTO t1 SELECT f1, f2 + 5 FROM t1;
INSERT INTO t1 SELECT f1, f2 + 10 FROM t1;
INSERT INTO t1 SELECT f1, f2 + 20 FROM t1;
INSERT INTO t1 SELECT f1, f2 + 40 FROM t1;
ANALYZE TABLE t1;
EXPLAIN SELECT f1, f2 FROM t1 WHERE f2 > 40;
MySQLのインデックススキャンは、節に従い、その後、すべての行のために選択することができるf2 > 40
条件WHERE
最終的な結果セットを生成します。フルスキャン範囲索引スキャンよりも効果が、いかなる条件が最初のインデックスにリストされていないがあるので、この場合に使用することができないf1
上に。しかし、MySQLの8.0.13から出発して、オプティマイザは、走査範囲の主走査範囲の「スキャンスキップ」と呼ばれる方法を使用することができる複数回に分割し、そして、結果は、複数のスキャンを返さマージされます。
次のように実行するアルゴリズムは次のようになります。
- 異なる値のインデックスを取得(
f1 = 1
)。 - 第一の構成と第2のインデックス範囲に応じて(
f1 = 1 AND f2 > 40
)。 - レンジ・スキャンを実行します。
- 異なる値でインデックスを取得(
f1 = 2
)。 - 第一の構成と第2のインデックス範囲に応じて(
f1 = 2 AND f2 > 40
)。 - レンジ・スキャンを実行します。
MySQLは各範囲の作図線を満たしていないスキップされますので、アクセス回線の数を減らすために、このポリシーを使用してください。これは、アクセス方法は、次のような場合に適用される「スキャンスキップ」:
- テーブルTは、インデックスがフォームされた少なくとも1つの複合インデックスを有する([A_1、...、A_
k
、】B_1、...、B_m
、C [、D_1、...、D_n
])。AとDキー部分は空であってもよいが、B及びCは、非空でなければなりません。。 - クエリは、1つのテーブルのみを使用しています。
- クエリは使用しません
GROUP BY
かDISTINCT
。 - クエリの参照インデックス内の列のみ。
- プレフィックスA_1は、...、A_ *
k
*同じ述語でなければならない、と彼らは一定でなければなりません。これには、IN()
。 - クエリは、関節の問い合わせでなければなりません。つまり、条件。
AND
OR
- 範囲条件Cが存在する必要があります。
- Dフィールドにフィルタ条件を可能にするが、範囲条件Cで使用しなければなりません
ジャンプの範囲スキャンの場合はSQL、使用がその実行計画を確認するためにEXPLAIN、あなたが見ることができます。
- そこ列内の余分な実行計画出力:スキップスキャンの使用インデックス
- possible_keysで実行計画の出力を表示する列がインデックスに使用することができます
2.2ラインの最適化の範囲コンストラクタ式
オプティマイザは、クエリの形で使用するスキャンアクセス方法を範囲とすることができます:
SELECT ... FROM t1 WHERE ( col_1, col_2 ) IN (( 'a', 'b' ), ( 'c', 'd' ));
使用走査範囲を最適化するために、クエリは次の基準を満たしている必要があります。
-
NOT IN()を使用せず、唯一のIN()述語を使用しました。
-
左側IN()述部では、行は、列参照の構成のみを含んでいます。
-
右側IN()述語では、ラインは、実行時定数の構成のみが含まれています。
-
右側述語IN()、行コンストラクタ複数のオン。
参考:最適化SELECT文