2017-11-19 4 views
1

は、次のSQLクエリを仮定:インデックスを作成せずに、MySQLで列選択性メタデータを取得する方法は?

SELECT col1,col2 from table where col1 > 5 and col2 > 8 

私は両方の条件が範囲条件であるため、MySQLは、同じテーブルインデックスを使用して、両方の列に調べることができないと信じています。 したがって、私はこのようなシナリオ(おそらく最も選択的なもの)でどの列をインデックス化するのかを判断する最良の方法は何かを理解しようとしています。

MySQLメタデータは、実際に両方のオプションのインデックスを作成してカーディナリティ情報を調べることなく、列AまたはBがより選択的であるかどうかを識別できる方法でアクセスできますか?

編集:明確にするために、目標は、インデックスなしで実行するために永遠にかかるクエリであってもそれを行う方法を見つけることです(この場合、行の数は問題になりません)。

答えて

1

このクエリの実行に問題はありますか?

select count(*), 
     sum(col1 > 5), 
     sum(col2 > 8), 
     sum(col1 > 5 and col2 > 8) 
from t; 

2番目と3番目の列の間で最も小さい値が選択されます。

注:両方の列をインデックスに入れることは、依然として価値があります。 MySQLは、データページ内のデータを参照することなく、where句に2番目のキーを使用できる必要があります。

+0

私は明示的に質問を編集しませんでしたが、私の目標は、関連するカウント(*)クエリがインデックスなしで実行されるまで永遠にかかる場合でも、正しいインデックスを識別できることです。私は、MySQLのオプティマイザがそれを行うかどうか、どのようにして同じことを模倣しようとしています。 – Tomer

+0

@Tomer - 私は何年も前から、インデックスを自動的に生成する方法を熟考してきました。私が持っている最高のものは[_ Cookbook_](http://mysql.rjweb.org/doc.php/index_cookbook_mysql)です。 –

2

クエリには、col1col2が含まれています。これは、INDEX(col1,col2)INDEX(col2,col1)が「カバーしている」ことを意味します。 「全体のクエリはインデックスのB木で実行することができるので、カバーは、あなたがSELECTリストに別の列を追加した場合、それはもはやカバーされません。

。余分なブーストを与えるしかし、問題は、およそれましたインデックスに列を入れる順序 2次元の配列として考えるcol1 > 5 and col2 > 8は、その2次元配列の右下を指します。MySQLは本質的に右半分または下半分をスキャンする必要があります1次元インデックスは最初に行または列によって順序付けされるので、配列の '半分'です。

最適化の「新しい」「MRR」機能では、では、半分ではなくコーナーにフォーカスを合わせることができます。これを見つける方法は次のとおりです。

add one index 
FLUSH STATUS; 
SELECT ... 
SELECT SESSION STATUS LIKE 'Handler%'; 
drop that index 

他のインデックスと同じように繰り返します。

次に、Handlerの値を比較します。最大の数字は、タッチされたインデックス(またはデータ)行の数を示します。

よりシンプルな答え

クエリでのみ列はcol1col2ある場合には、(いずれかの順序で)INDEX(col1, col2)を追加します。

さらに列が含まれている場合は、INDEX(col1)INDEX(col2)を追加してください。オプティマイザはそれらの間を選択します。

+0

この回答をありがとうリック。実際には、カウントクエリを実行せずに追加するインデックスを決定する方法や、インデックスを追加してそれぞれに「何かをテストする」方法を模索していました。 MySQLには、私がその決定を下す可能性のあるメタデータから得られる情報がありますか? 大規模なテーブルやクエリでは、特に多くのクエリを最適化する場合に、インデックスの追加と削除の試行錯誤が長時間かかることがあります。私はそれが存在する場合、それを避ける方法を探しています。 – Tomer

+1

2つの範囲は扱いが面倒です。私は自分の答えに「簡単な答え」を付け加えました。 –

関連する問題