Note that there are some explanatory texts on larger screens.

plurals
  1. POWhy does removing this index in MySQL speed up my query 100x?
    primarykey
    data
    text
    <p>I have the following MySQL table (simplified):</p> <pre><code>CREATE TABLE `track` ( `id` int(11) NOT NULL AUTO_INCREMENT, `title` varchar(256) NOT NULL, `is_active` tinyint(1) NOT NULL, PRIMARY KEY (`id`), KEY `is_active` (`is_active`, `id`) ) ENGINE=MyISAM AUTO_INCREMENT=7495088 DEFAULT CHARSET=utf8 </code></pre> <p>The 'is_active' column marks rows that I want to ignore in most, but not all, of my queries. I have some queries that read chunks out of this table periodically. One of them looks like this:</p> <pre><code>SELECT id,title from track where (track.is_active=1 and track.id &gt; 5580702) ORDER BY id ASC LIMIT 10; </code></pre> <p>This query takes over a minute to execute. Here's the execution plan:</p> <pre><code>&gt; EXPLAIN SELECT id,title from track where (track.is_active=1 and track.id &gt; 5580702) ORDER BY id ASC LIMIT 10; +----+-------------+-------+------+----------------+--------+---------+-------+---------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+----------------+--------+---------+-------+---------+-------------+ | 1 | SIMPLE | t | ref | PRIMARY,is_active | is_active | 1 | const | 3747543 | Using where | +----+-------------+-------+------+----------------+--------+---------+-------+---------+-------------+ </code></pre> <p>Now, if I tell MySQL to ignore the 'is_active' index, the query happens instantaneously.</p> <pre><code>&gt; EXPLAIN SELECT id,title from track IGNORE INDEX(is_active) WHERE (track.is_active=1 AND track.id &gt; 5580702) ORDER BY id ASC LIMIT 10; +----+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+ | 1 | SIMPLE | t | range | PRIMARY | PRIMARY | 4 | NULL | 1597518 | Using where | +----+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+ </code></pre> <p>Now, what's really strange is that if I FORCE MySQL to use the 'is_active' index, the query once again happens instantaneously!</p> <pre><code>+----+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+ | 1 | SIMPLE | t | range | is_active |is_active| 5 | NULL | 1866730 | Using where | +----+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+ </code></pre> <p>I just don't understand this behavior. In the 'is_active' index, rows should be sorted by is_active, followed by id. I use both the 'is_active' and 'id' columns in my query, so it seems like it should only need to do a few hops around the tree to find the IDs, then use those IDs to retrieve the titles from the table. </p> <p>What's going on?</p> <p>EDIT: More info on what I'm doing:</p> <ul> <li>Query cache is disabled</li> <li>Running OPTIMIZE TABLE and ANALYZE TABLE had no effect</li> <li>6,620,372 rows have 'is_active' set to True. 874,714 rows have 'is_active' set to False.</li> <li>Using FORCE INDEX(is_active) once again speeds up the query.</li> <li>MySQL version 5.1.54</li> </ul>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload