2009-08-09 35 views
29

これは私が永遠に持っていた質問です。MySQLのインデックスと注文

私が知る限り、インデックスの順序は重要です。したがって、[first_name, last_name]のようなインデックスは[last_name, first_name]と同じではありません。

私はORMを使用しておりますので、私は唯一の最初のインデックスを定義し、それが唯一の

SELECT * FROM table WHERE last_name="doe" AND first_name="john"; 

ため

SELECT * FROM table WHERE first_name="john" AND last_name="doe"; 

ずに使用することを意味していた場合、私は見当がつかないこれらの列が呼び出される順序です。それは、すべての順列にインデックスを追加しなければならないということですか? 2列のインデックスがあればそれが可能ですが、インデックスが3列または4列の場合はどうなりますか?

答えて

44

クエリ条件がインデックスのPARTにのみ適用される場合、インデックスの順序は重要です。考えてみましょう:

  1. SELECT * FROM table WHERE first_name="john" AND last_name="doe"

  2. SELECT * FROM table WHERE first_name="john"

  3. SELECT * FROM table WHERE last_name="doe"

あなたのインデックスがある場合(first_namelast_name)クエリ#3ウォン、1及び2は、それを使用します問い合わせます't。 インデックスが(last_name,first_name)の場合、クエリ1とクエリ3が使用されますが、クエリ#2は使用されません。 WHERE句内の条件の順序を変更しても、どちらの場合でも効果はありません。

詳細はアップデートhere

次のとおりです。
上記の場合には明確ではありません - クエリ条件の列がインデックスの左端の接頭辞を形成する場合、MySQLはインデックスのみを使用することができます。上記のクエリ#2では、first_nameのみに基づいており、first_nameは(last_name,)のインデックスの一番左のプレフィックスではないため、(last_namefirst_name)のインデックスを使用することはできません。

クエリ内の条件の順序は関係ありません。上記のクエリ#1は、条件がfirst_namelast_nameであり、一緒になって、(last_name,)のインデックスの最前面の接頭辞を形成するため、(last_namefirst_name)のインデックスを使用することができます。

+0

だから私はSELECT * FROMテーブルwhere last_name = "doe" AND first_name = "john"はそうではないと思いますか? これは、すべてのクエリ構築が私のORMによって隠されているため、2つのインデックスを定義する必要があります...私は定義する3つの列にインデックスがあるので、本当にうんざりです... –

+1

いいえ、あなたは誤解しています。 'last_name' =" doe "と' first_name' = "john"クエリは、( 'first_name'、' last_name')または( 'last_name'、' first_name')インデックスだけを使用します。 – ChssPly76

+0

質問:2 AND条件のクエリの場合、クエリの条件と比較してインデックスが「反転」されているかどうか、またはそれらの列の基数によって異なります。 – Mihai

5

ChssPly76は、ブール式の順序がインデックス内の列の順序と一致していなくてもかまいません。ブール演算子はcommutativeであり、MySQLオプティマイザは、ほとんどの場合、式をインデックスにどのようにマッチさせるかを知るのに十分にスマートです。

また、MySQLのEXPLAIN機能の使い方を学ぶ必要があるので、オプティマイザが特定のクエリに対して選択するインデックスを自分で確認することもできます。

+2

+1の説明です。 – Petrogad

+0

MySQL Workbenchは、 'Execution Plan'の下に' EXPLAIN'情報をグラフィカルに表示します。 –

2

答えを少し長くして、一度に完全にすべてをクリスタルクリアにしてみませんか?

テーブルに複数列のインデックスがある場合は、インデックスの最前面の任意のプレフィックスを使用して、オプティマイザが行を検索できます。たとえば、3列のインデックスが(col1, col2, col3)の場合、(col1)(col1, col2)、および(col1, col2, col3)にインデックス検索機能があります。

インデックスがインデックスの一番左のプレフィックスを形成しない場合、MySQLはインデックスを使用できません。あなたがここに示されているSELECTステートメントがあるとします。

SELECT * FROM tbl_name WHERE col1=val1; 
SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2; 

SELECT * FROM tbl_name WHERE col2=val2; 
SELECT * FROM tbl_name WHERE col2=val2 AND col3=val3; 

インデックスが(col1, col2, col3)に存在する場合、最初の2つのクエリがインデックスを使用しています。 3番目と4番目のクエリにはインデックス付きの列が含まれますが、(col2)(col2, col3)は接頭辞の一番左にはありません(col1, col2, col3)です。 - MySQL dev