いくつかのルックアップテーブルとプライマリログテーブルを使用するイベント追跡システムに取り組んでいます。私が書いているレポートでは、統計を表示するオブジェクトを選択できます。インターフェイスは、重要度の低い順にすべてのオブジェクトを表示します(つまり、ヒット)。
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を使用して取得できるように最適化されていますか?
これが元のクエリです
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
;
取得するのと同じくらい最適化されているように見えます
クエリを変更します
SELECT
el.object_id,
leo.object_desc,
SUM(ISNULL(leo.object_id)=0) 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
;
これにより、特にルックアップオブジェクトのないイベントログの場合、より正確なカウントが得られる可能性があります。