Table Structure:
CREATE TABLE IF NOT EXISTS `newsletters`
(
`id` int(11) NOT NULL auto_increment,
`last_update` int(11) default NULL,
`status` int(11) default '0',
`message_id` varchar(255) default NULL,
PRIMARY KEY (`id`),
KEY `status` (`status`),
KEY `message_id` (`message_id`),
KEY `last_update` (`last_update`)
)
ENGINE=MyISAM DEFAULT CHARSET=latin1;
The Query:
SELECT id, last_update
FROM newsletters
WHERE status = 1
ORDER BY last_update DESC
LIMIT 0, 100
newsletters
table has over 3 million records
Query explain:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE newsletters range status status 5 NULL 3043354 Using where; Using filesort
So why is it not using filesort
, and how is it a range
query?
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.
To avoid a filesort, you have to find a way to get what you want without running into any of those (many) documented conditions. Increase the size of the sort_buffer_size variable. Increase the size of the read_rnd_buffer_size variable.
The creating sort index state appears when a query with an ORDER BY or GROUP BY clause can't use an existing index to perform the operation. In this case, MySQL needs to perform a more expensive filesort operation. This operation is typically performed in memory if the result set isn't too large.
Indexes are used to find rows with specific column values quickly. Without an index, MySQL must begin with the first row and then read through the entire table to find the relevant rows. The larger the table, the more this costs.
It's using filesort
to sort on last_update
. You can avoid the filesort that by changing the index to status, last_update
, so MySQL finds all rows with status 1 in the right order.
To further optimize, change the index to status, last_update, id
. That allows MySQL to satisfy the query just by looking at the index, without a table lookup.
CREATE INDEX idx_newsletters_status
ON newsletters(status, last_update, id);
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