Query A takes 3 seconds or more to produce 294 results:
SELECT user_id, id
FROM web_useradvisory
WHERE emailed IS NULL
ORDER BY user_id ASC, id ASC;
However, Query B takes about 10 milliseconds (!!) to produce the same 294 results:
SELECT user_id, id
FROM web_useradvisory
WHERE user_id IN (SELECT id FROM auth_user) AND emailed IS NULL
ORDER BY user_id ASC, id ASC;
EXPLAIN
says both queries are using the same index, and web_useradvisory.user_id
has a non-nullable foreign key index to auth_user.id
. FYI there are only 5 distinct user IDs among the 294 records.
Query A:
mysql> EXPLAIN SELECT user_id, id FROM web_useradvisory WHERE emailed IS NULL ORDER BY user_id ASC, id ASC;
+----+-------------+------------------+------------+-------+---------------+------------------+---------+------+---------+----------+--------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------------+------------+-------+---------------+------------------+---------+------+---------+----------+--------------------------+
| 1 | SIMPLE | web_useradvisory | NULL | index | NULL | user_emailed_idx | 13 | NULL | 5075623 | 10.00 | Using where; Using index |
+----+-------------+------------------+------------+-------+---------------+------------------+---------+------+---------+----------+--------------------------+
Query B:
mysql> EXPLAIN SELECT user_id, id FROM web_useradvisory WHERE user_id IN (SELECT id FROM auth_user) AND emailed IS NULL ORDER BY user_id ASC, id ASC;
+----+-------------+------------------+------------+-------+--------------------------------------------------------------------------------------------------------+------------------+---------+------------------------------+------+----------+----------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------------+------------+-------+--------------------------------------------------------------------------------------------------------+------------------+---------+------------------------------+------+----------+----------------------------------------------+
| 1 | SIMPLE | auth_user | NULL | index | PRIMARY | username | 152 | NULL | 170 | 100.00 | Using index; Using temporary; Using filesort |
| 1 | SIMPLE | web_useradvisory | NULL | ref | web_useradvisory_user_id_a9c47ffb_fk_auth_user_id,user_emailed_idx,user_localtime_idx,user_done_lt_idx | user_emailed_idx | 13 | TMVRemote.auth_user.id,const | 2 | 100.00 | Using where; Using index |
+----+-------------+------------------+------------+-------+--------------------------------------------------------------------------------------------------------+------------------+---------+------------------------------+------+----------+----------------------------------------------+
SHOW INDEXES
shows the following:
SHOW INDEXES FROM web_useradvisory;
+------------------+------------+----------------------------------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+------------------+------------+----------------------------------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| web_useradvisory | 0 | PRIMARY | 1 | id | A | 5001672 | NULL | NULL | | BTREE | | |
| web_useradvisory | 1 | web_useradvisory_advisory_id_a8bea1ea_fk_web_advisory_id | 1 | advisory_id | A | 135733 | NULL | NULL | | BTREE | | |
| web_useradvisory | 1 | web_useradvisory_user_id_a9c47ffb_fk_auth_user_id | 1 | user_id | A | 69 | NULL | NULL | | BTREE | | |
| web_useradvisory | 1 | user_emailed_idx | 1 | user_id | A | 72 | NULL | NULL | | BTREE | | |
| web_useradvisory | 1 | user_emailed_idx | 2 | emailed | A | 2361395 | NULL | NULL | YES | BTREE | | |
| web_useradvisory | 1 | user_localtime_idx | 1 | user_id | A | 72 | NULL | NULL | | BTREE | | |
| web_useradvisory | 1 | user_localtime_idx | 2 | localtime | A | 4674121 | NULL | NULL | | BTREE | | |
| web_useradvisory | 1 | user_done_lt_idx | 1 | user_id | A | 7409 | NULL | NULL | | BTREE | | |
| web_useradvisory | 1 | user_done_lt_idx | 2 | done | A | 9261 | NULL | NULL | | BTREE | | |
| web_useradvisory | 1 | user_done_lt_idx | 3 | localtime | A | 4897349 | NULL | NULL | | BTREE | | |
+------------------+------------+----------------------------------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
Why doesn't Query A run as quickly as Query B? Query B's additional user_id WHERE
condition doesn't actually further constrain the results, since the foreign key constraint on web_useradvisory.user_id
already requires it to be a value from the list auth_user.id
. It seems like my subquery selecting all the auth_user.id
values in Query B is giving mysql
a hint that the database engine fails to infer from Query A.