私は非常に大きなテーブル(〜1.7M行)の最適化問題を抱えています。数値カラムのMySQLインデックスはクエリを遅くします
行を選択するときに2つの列が使用されます。それらをcolAとcolBとします。彼らは、 '二重'(小数点以下5桁)タイプの両方範囲であるから:
で、colA:-90〜90 COLB:インデックスなし-180〜180
、フォームの任意のクエリ:
SELECT * FROM table where colA BETWEEEN a and b AND colB BETWEEN c and d
は、(a、b)、(c、d)の範囲にかかわらず(MySQLはすべての行を調べなければならないため)ほぼ同じ時間(〜1秒)かかります。
私は2つのことが起こる、コーラとCOLBにインデックスを追加する場合:クエリ(a、b)は&(C、D)の範囲には、例えば、小さい:
SELECT * FROM table where colA BETWEEEN -4 and 4 AND colB BETWEEN 3 and 7
実行非常に迅速に(約1/10秒)。ただし、照会された値の範囲で実行時間が長くなります。たとえば:
SELECT * FROM table where colA BETWEEEN -80 and 80 AND colB BETWEEN -150 and 150
は、実行する分程度かかります。
私はB-treeが文字列としてどのように機能するのか知っていますが、データが数値で、範囲を使ってクエリが実行されているときは、メカニズムがわかりません。
誰でもこのクエリを最適化する方法を提案できたら、私は感謝します。 1つの考えは、小さな範囲にインデックスを使用し、大きなものに対しては使用しないようMySQLに指示することですが、これを可能にするコマンドを見つけることができませんでした。
おかげ
編集:私は愚かな言及を忘れてしまった何かがあり
説明しています。結果はrand()によって整理されます - これは非効率的であることを認識していますが、テーブルからランダムに限られた数の行を取得する方法は他にありません。
rand()を追加しても、インデックスがない場合の実行時間には影響しませんが、存在する時間を大幅に短縮します。
EDIT2:これは複合インデックスを使用しています。
小さな範囲:
9783行
"RAND(BY -10と5 ORDERの間に35と38とCOLB間コーラ)20を制限する場合、テーブルSELECT * FROM説明" (速い)INDEX WITH
+----+-------------+-------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+---------+-------------+
| 1 | SIMPLE | table | ALL | NULL | NULL | NULL | NULL | 1673784 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+---------+-------------+
(非常に速い)NO INDEXない
+----+-------------+-------+-------+---------------+------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+------+---------+------+--------+-------------+
| 1 | SIMPLE | table | range | test | test | 18 | NULL | 136222 | Using where |
+----+-------------+-------+-------+---------------+------+---------+------+--------+-------------+
広い範囲:
"セレクト説明* -80と80とRAND BY COLB ORDER -150〜150の間のコーラ()20を制限テーブルから、"
1631862行
NO INDEX(速い)INDEX(非常に遅い:> 60秒)WITH
+----+-------------+-------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+---------+-------------+
| 1 | SIMPLE | table | ALL | NULL | NULL | NULL | NULL | 1673784 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+---------+-------------+
:要約する
3210EDIT3: (すべてのクエリが20行を返すように制限されています)
指標とランドとの大きな範囲():45秒
大きな範囲ランド無し()は、インデックス付き:0.003秒
大きなランドとの範囲、無度:1秒
大きい範囲せずにrand、インデックスなし:0.003秒
異常は次のとおりです。「インデックス付きの大きな範囲()、45秒」。
を無効にするインデックスをしてください強制することができます。 2番目のケースではインデックスが使用されていないこともわかります – zerkms
"colAとcolBにインデックスを追加すると" ---これを明確にしてください。あなたが私たちに示したクエリについては、最も効率的なのは2 **の分離した**インデックスを作成することです。 1つは「ColA」、もう1つは「ColB」です。 – zerkms
@zerkms:2つの分離されたインデックスがコンポジットインデックスより効率的なのはなぜですか?表示されたクエリでは、両方の列がwhere句にANDと組み合わされていますが、これは複合インデックスの完璧なシナリオのようです。 – Thilo