2011-12-08 12 views
4

私はこれではなく、単純なクエリは、約8秒かかる単純なテーブルにいくつかの単純なインデックスMySQLはGROUP BYのインデックスを使用するかどうかをどのように決定しますか?

Key_name   Cardinality 
PRIMARY    1510443 
piece_to_bin_id  100696 

stock_ledger_id INT(10) (Primary) 
piece_to_bin_id INT(10) 
quantity   INT(11) 
create_datetime TIMESTAMP 
... and a few VARCHARs 

を持っている:

id select_type table  type possible_keys key key_len ref rows Extra       
1 SIMPLE  stock_ledger ALL NULL   NULL NULL NULL 1512976 Using temporary; Using filesort 
を:

SELECT piece_to_bin_id, 
     SUM(quantity), 
     MAX(create_datetime) 
FROM stock_ledger 
GROUP BY piece_to_bin_id 

をここにEXPLAINです

私は私は、インデックスを強制的に約0.5秒にそれをダウンさせることが分かっ:

SELECT piece_to_bin_id, 
     SUM(quantity), 
     MAX(create_datetime) 
FROM stock_ledger 
FORCE INDEX (piece_to_bin_id) 
GROUP BY piece_to_bin_id 

次に[次のようなルックスをEXPLAIN:

id select_type table  type possible_keys key    key_len ref rows Extra 
1 SIMPLE  stock_ledger index NULL   piece_to_bin_id 4  NULL 1512976 

私は、MySQL 5.1.41を使用していますテーブルはMyISAMで、前にANALYZE TABLEを実行しました。

私は「MySQLはもう一度間違ってしまいました。単にインデックスを強制する」とか、MySQLがフルテーブルスキャンを使用する実際の理由はありますか?多分私は修正することができますか?

+1

は、まだ完全なテーブルスキャンを使用していますが、ほぼ同じです。 – ajreal

+0

'SQL_NO_CACHE'命令を使用しても、2番目のクエリは1秒未満で実行されますか? ( 'SELECT SQL_NO_CACHE <残りのクエリ>') –

答えて

1

クエリには、とにかく完全なテーブルスキャンが必要です。mysqlはキー値からの追加の遷移も避けようとしている可能性があります。クエリは、複合(piece_to_bin_id、create_datetime)インデックスまたはさらには(piece_to_bin_id、create_datetime、quantity)の恩恵を受ける可能性があります。後者はカバレッジ指数になります。

UPD

16倍速く結果があなたの場合のデータ分布(create_datetimeによって並べ替え同じpiece_to_bin_idと、おそらく、多くの隣接する行)から来ているようです。 MyISAMは、結果として得られる行の数を減らすクエリのインデックスを使用しているようです。なぜなら、それらの使用はランダムなディスクI/O操作を意味するからです。

は、私はそれに注意を引かれたことがないが、10K行のテーブルの上に私の現在のテストでは、MyISAMテーブルでも同様にクエリをソートするためのインデックスを使用していないことを示している:indexed_fieldがある場合でも

SELECT indexed_field, another_field 
FROM a_table 
ORDER BY indexed_field; 

主キー

+0

これは、クエリが16倍高速になっても、MySQLがそれほど適切でないインデックスを使用しない理由を説明していません。ただし、カバレッジ・インデックスを提供すると、そのインデックスが使用されます。 – AndreKR

+0

@andrekr、私は私の答えを更新しました。 – newtover

関連する問題