私は、プライマリロギングテーブルだけでなく、いくつかのルックアップテーブルを使用するイベントトラッキングシステムに取り組んでいます。私が書いているレポートでは、統計を表示するオブジェクトを選択できます。インターフェースは、重要度の低い順にすべてのオブジェクトを表示します(つまり、ヒット)。
2つのテーブルのスキーマ(わずかにトリミングされていますが、要点はわかります):
CREATE TABLE IF NOT EXISTS `event_log` (
`event_id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(5) DEFAULT NULL,
`object_id` int(5) DEFAULT NULL,
`event_date` datetime DEFAULT NULL,
PRIMARY KEY (`event_id`),
KEY `user_id` (`user_id`),
KEY `object_id` (`object_id`)
);
CREATE TABLE IF NOT EXISTS `lookup_event_objects` (
`object_id` int(11) NOT NULL AUTO_INCREMENT,
`object_desc` varchar(255) NOT NULL,
PRIMARY KEY (`object_id`)
);
私が問題を抱えているクエリは以下です。 〜100エントリのテーブルでは問題なく動作しますが、EXPLAINは少し心配しています。
explain SELECT
el.object_id,
leo.object_desc,
COUNT(el.object_id) as count_rows
FROM
event_log el
LEFT JOIN lookup_event_objects leo ON leo.object_id = el.object_id
GROUP BY
el.object_id
ORDER BY
count_rows DESC,
leo.object_desc ASC
戻り値:Using index; Using temporary; Using filesort
それで、MySQLがtemporary
とfilesort
にフォールバックするためのスキーマおよび/またはクエリの何が問題になっていますか?または、ORDER BYを使用して取得できるように最適化されていますか?
さて、 ドキュメント は、「一時的な使用」が表示される正確な理由を示しています。
一時テーブルは、次のような条件で作成できます。
ORDER BY句と別のGROUP BY句がある場合、またはORDER BYまたはGROUP BYに結合キューの最初のテーブル以外のテーブルの列が含まれている場合、一時テーブルが作成されます。
DISTINCTとORDER BYを組み合わせると、一時テーブルが必要になる場合があります。
SQL_SMALL_RESULTオプションを使用する場合、MySQLは、クエリにディスク上のストレージを必要とする要素(後述)も含まれていない限り、メモリ内の一時テーブルを使用します。
クイックスキャンでは、#1に苦しんでいることがわかります。
そして このブログ は2009年から「filesortを使用する」とは、インデックスを使用してソートを実行できないことを意味します。計算フィールドで順序付けしているので、それも当てはまります。
だから、それが「間違っている」のです。
MySQL 5.7用に更新( src ):
サーバーは、次のような条件下で一時テーブルを作成します。
後で説明するいくつかの例外を除き、UNIONステートメントの評価。
TEMPTABLEアルゴリズム、UNION、または集約を使用するビューなど、一部のビューの評価。
派生テーブル(FROM句のサブクエリ)の評価。
サブクエリまたは準結合マテリアライゼーション用に作成されたテーブル(セクション8.2.2「サブクエリ、派生テーブル、およびビュー参照の最適化」を参照)。
ORDER BY句と別のGROUP BY句を含むステートメント、またはORDER BYまたはGROUP BYに結合キューの最初のテーブル以外のテーブルの列が含まれるステートメントの評価。
DISTINCTをORDER BYと組み合わせて評価するには、一時テーブルが必要になる場合があります。
SQL_SMALL_RESULT修飾子を使用するクエリの場合、MySQLは、ディスク上のストレージを必要とする要素(後述)もクエリに含まれていない限り、メモリ内の一時テーブルを使用します。
同じテーブルから選択して挿入するINSERT ... SELECTステートメントを評価するために、MySQLは内部一時テーブルを作成してSELECTからの行を保持し、それらの行をターゲットテーブルに挿入します。セクション13.2.5.1「INSERT ... SELECT構文」を参照してください。
複数テーブルのUPDATEステートメントの評価。
GROUP_CONCAT()またはCOUNT(DISTINCT)式の評価。
これらは、一時テーブルが作成される次の条件です。 UNIONクエリは一時テーブルを使用します。
TEMPTABLEアルゴリズムを使用して評価されたビューや、UNIONまたは集計を使用したビューなど、一部のビューには一時テーブルが必要です。
ORDER BY句と別のGROUP BY句がある場合、またはORDER BYまたはGROUP BYに結合キューの最初のテーブル以外のテーブルの列が含まれている場合、一時テーブルが作成されます。
DISTINCTとORDER BYを組み合わせると、一時テーブルが必要になる場合があります。
SQL_SMALL_RESULTオプションを使用する場合、MySQLは、クエリにディスク上のストレージを必要とする要素(後述)も含まれていない限り、メモリ内の一時テーブルを使用します。
Mysqlでこのリンクをたどってください: http://dev.mysql.com/doc/refman/5.1/en/internal-temporary-tables.html