2010-12-16 2 views
2
SELECT COUNT(*) AS cnt 
FROM products 
WHERE ExternalProductId IS NOT NULL 
GROUP BY SourceId, ExternalProductId 
HAVING cnt > 1 

(ExternalProductId、SourceId、AnotherField)にインデックスがあります。索引が使用されていることをExplainが示しています。これは、説明の「エクストラ」欄に印字されています次のクエリのコピーテーブルのデータはなぜですか?

Using where; Using index; Using temporary; Using filesort 

私はSHOWのPROCESSLIST経由で参照クエリを実行すると:

Copying to tmp table on disk 

私はこのクエリは、インデックス上の所定の位置に動作するように微調整することができますか?また、このテーブルで同時に作業している他のプロセスが原因で、結果が多少不正確になっても構わないのですか?クエリのパフォーマンスを向上させるために分離レベルを変更できますか?

+2

あなたはいくつかの誤解があると思います。一時テーブルとは、テーブルからすべてのデータをコピーしてその作業を行うことを意味するものではありません。これは、後で処理するために中間結果を一時テーブルにコピーすることを意味します。テンポラリテーブルには、ExternalProductIDがnullではないレコードとcntカラムが含まれているため、 'HAVING'句を評価できます。次に、トランザクションの分離は一時テーブルとは関係ありません。 – bot403

+0

@ bot403 - DBAと話をしたところ、彼はあなたに同意します。私はあなたのコメントが実際にこの質問に最も良い答えであると信じています。 – ripper234

+0

はい、答えは#1とajrealのインデックス提案の両方であると思います。 – bot403

答えて

3

GROUP BYの列を、複合インデックスの最初の2つのフィールドの順序に対応させると、その複合インデックスがより効果的に使用されます。

SELECT COUNT(*) AS cnt 
FROM products 
WHERE ExternalProductId IS NOT NULL 
GROUP BY ExternalProductId, SourceId 
HAVING cnt > 1 

あなたのクエリ実行平野は'Using where; Using index'に変わるべきであり、他のGROUP BYによる一時的なテーブルとfilesortレコードの両方を取り除きます。

同じ結果が得られますが、少しずつ違いがあります。

+0

見栄えが良い、説明は本当に一時テーブルを表示していません。私は、クエリランタイムを測定して、違いがあるかどうかを確認します。 – ripper234

0

しようとするカップルの事:

  1. MySQLは自動的にして、グループでソートされます。ソート順が気にしない場合は、 'ORDER BY NULL'節を追加してください。これはfilesortとおそらくtempテーブルを取り出します。

  2. カウント(*)を削除し、ワイルドカードではなくインデックスの列名を使用します。

また、あなたのインデックスは何ですか?完全なテーブル作成ステートメントを表示できますか?

+0

ORDER BY NULLは依然として一時テーブルを使用しています。 – ripper234

関連する問題