Question

We're upgrading mysql from 5.5 to 5.6 and some queries are deadly slow now.

Queries that took 0.005 seconds before are now taking 49 seconds.

Queries on 5.6 are skipping the indexes, it seems:

+----+-------------+-------+-------+----------------------------------------------------+---------+---------+------+--------+-------------+
| id | select_type | table | type  | possible_keys                                      | key     | key_len | ref  | rows   | Extra       |
+----+-------------+-------+-------+----------------------------------------------------+---------+---------+------+--------+-------------+
|  1 | SIMPLE      | pens  | index | index_contents_on_slug,index_contents_on_slug_hash | PRIMARY | 4       | NULL | 471440 | Using where |
+----+-------------+-------+-------+----------------------------------------------------+---------+---------+------+--------+-------------+
1 row in set (0.00 sec)

But are not being skipped on 5.5:

+----+-------------+-------+-------------+----------------------------------------------------+----------------------------------------------------+---------+------+------+----------------------------------------------------------------------------------------------+
| id | select_type | table | type        | possible_keys                                      | key                                                | key_len | ref  | rows | Extra                                                                                        |
+----+-------------+-------+-------------+----------------------------------------------------+----------------------------------------------------+---------+------+------+----------------------------------------------------------------------------------------------+
|  1 | SIMPLE      | pens  | index_merge | index_contents_on_slug,index_contents_on_slug_hash | index_contents_on_slug_hash,index_contents_on_slug | 768,768 | NULL |    2 | Using union(index_contents_on_slug_hash,index_contents_on_slug); Using where; Using filesort |
+----+-------------+-------+-------------+----------------------------------------------------+----------------------------------------------------+---------+------+------+----------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

Both DBs were created from the same mysql dump.

Are these indexes not being constructed when I do the import on 5.6? How do I force the index creation?

The query:

SELECT  `pens`.* FROM `pens`  WHERE (slug_hash = 'style' OR slug = 'style') ORDER BY `pens`.`id` DESC LIMIT 1

Edit: Removed the schema

Was it helpful?

Solution

Ultimately the accepted answer above is correct.

The help from @RandomSeed got me thinking in the right direction. Basically the optimization plans created in 5.6 are significantly different from those in 5.5, so you'll probably have to rework your query, much like I did.

I did not end up using the FORCE INDEX, but instead removed portions of the query until I determined what was causing 5.6 to miss the index. Then I reworked the application logic to deal with that.

OTHER TIPS

The slow query in v5.6 is caused by the engine being unable to, or deciding not to, merge the two relevant indexes (index_contents_on_slug_hash, index_contents_on_slug) in order to process your query. Remember that a query may only use one index per table. In order to be able to take advantage of several indexes on the same table, it needs to pre-merge on-the-fly these indexes into one (in memory). This is the meaning of the index_merge and Using union(...) notices in your execution plan. This consumes time and memory, obviously.

Quick fix (and probably preferred solution anyways): add a two-colums index on slug and slug_hash.

ALTER TABLE pens ADD INDEX index_contents_on_slug_and_slug_hash (
    slug, slug_hash
);

Now your new server is probably unable to merge these indexes because it results in an index too large to fit in the buffer. Your new server probably has a much smaller value for key_buffer_size (if the table is MyISAM) or for innodb_buffer_pool_size (if InnoDB) than there used to be in your older installation.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top