I'm working on a event tracking system which uses a handful of lookup tables as well as the primary logging table. In a report I'm writing, an object can be selected to view statistics against. The interface shows all objects in order of decreasing importance (ie, hits).
The schema for the two tables (slightly trimmed down, but you get the gist):
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`) );
The query I'm having trouble with is below. It works fine with my table of ~100 entries, but the EXPLAIN worries me a little.
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
Returns: Using index; Using temporary; Using filesort
So -- what's wrong with my schema and/or query for MySQL to fall back on temporary
and filesort
? Or is it as optimized as it can get using ORDER BY?
A TEMPORARY table is visible only within the current session, and is dropped automatically when the session is closed. This means that two different sessions can use the same temporary table name without conflicting with each other or with an existing non- TEMPORARY table of the same name.
In MySQL, filesort is the catch-all algorithm for producing sorted results for ORDER-BY or GROUP-BY queries. MySQL has two algorithms for filesort, both the original and the modified algorithms are described in the user manual.
The filtered column indicates an estimated percentage of table rows that will be filtered by the table condition. That is, rows shows the estimated number of rows examined and rows × filtered / 100 shows the number of rows that will be joined with previous tables.
Well, the doc gives the exact reasons when "Using temporary" will appear:
Temporary tables can be created under conditions such as these:
If there is an ORDER BY clause and a different GROUP BY clause, or if the ORDER BY or GROUP BY contains columns from tables other than the first table in the join queue, a temporary table is created.
DISTINCT combined with ORDER BY may require a temporary table.
If you use the SQL_SMALL_RESULT option, MySQL uses an in-memory temporary table, unless the query also contains elements (described later) that require on-disk storage.
A quick scan shows that you suffer from #1.
And this blog from 2009 says that "using filesort" means that the sort can't be performed with an index. Since you're ordering by a computed field, that's going to be true, too.
So, that's what's "wrong".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With