[英]why is mysql not using the right index?
I have a problem where the correct index is no being used. 我有一个问题,其中没有使用正确的索引。
I have the following indexes on an innodb table (about 500,000 rows) : 我在innodb表(约500,000行)上具有以下索引:
+-------------+------------+------------------------+--------------+------------------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------------+------------+------------------------+--------------+------------------------+-----------+-------------+----------+--------+------+------------+---------+
| osdate_user | 0 | PRIMARY | 1 | id | A | 419700 | NULL | NULL | | BTREE | |
| osdate_user | 0 | email | 1 | email | A | 419700 | NULL | NULL | | BTREE | |
| osdate_user | 0 | username | 1 | username | A | 419700 | NULL | NULL | YES | BTREE | |
| osdate_user | 1 | lastvisit | 1 | lastvisit | A | 419700 | NULL | NULL | | BTREE | |
| osdate_user | 1 | active | 1 | active | A | 8 | NULL | NULL | YES | BTREE | |
| osdate_user | 1 | gender | 1 | gender | A | 88 | NULL | NULL | YES | BTREE | |
| osdate_user | 1 | regdate | 1 | regdate | A | 419700 | NULL | NULL | | BTREE | |
| osdate_user | 1 | lastupdate | 1 | lastupdate | A | 419700 | NULL | NULL | YES | BTREE | |
| osdate_user | 1 | password | 1 | password | A | 419700 | NULL | NULL | | BTREE | |
| osdate_user | 1 | age | 1 | age | A | 190 | NULL | NULL | YES | BTREE | |
| osdate_user | 1 | is_new | 1 | is_new | A | 8 | NULL | NULL | YES | BTREE | |
| osdate_user | 1 | private_photos | 1 | private_photos | A | 8 | NULL | NULL | | BTREE | |
| osdate_user | 1 | pictures_cnt | 1 | pictures_cnt | A | 10 | NULL | NULL | YES | BTREE | |
| osdate_user | 1 | pictures_cnt | 2 | private_photos | A | 10 | NULL | NULL | | BTREE | |
| osdate_user | 1 | status | 1 | status | A | 19 | NULL | NULL | | BTREE | |
| osdate_user | 1 | status | 2 | active | A | 19 | NULL | NULL | YES | BTREE | |
| osdate_user | 1 | status | 3 | gender | A | 19 | NULL | NULL | YES | BTREE | |
| osdate_user | 1 | status | 4 | age | A | 19 | NULL | NULL | YES | BTREE | |
| osdate_user | 1 | status | 5 | country | A | 7630 | NULL | NULL | YES | BTREE | |
| osdate_user | 1 | status | 6 | city | A | 46633 | NULL | NULL | YES | BTREE | |
| osdate_user | 1 | status | 7 | pictures_cnt | A | 83940 | NULL | NULL | YES | BTREE | |
| osdate_user | 1 | status | 8 | private_photos | A | 139900 | NULL | NULL | | BTREE | |
| osdate_user | 1 | status | 9 | lang | A | 209850 | NULL | NULL | | BTREE | |
| osdate_user | 1 | status | 10 | is_new | A | 209850 | NULL | NULL | YES | BTREE | |
+-------------+------------+------------------------+--------------+------------------------+-----------+-------------+----------+--------+------+------------+---------+
This query : 此查询:
EXPLAIN EXTENDED SELECT user.id, user.active
FROM osdate_user user
WHERE user.active =1
AND user.status = 'active'
AND user.gender = 'M'
AND user.age
BETWEEN 19
AND 35
AND user.pictures_cnt >0
AND user.private_photos = '0'
ORDER BY user.lastvisit DESC
LIMIT 0 , 24
Displays the following plan : 显示以下计划:
+----+-------------+---------+-------------+--------------------------------------------------------------+------------------------------+---------+---------------------------+-------+----------+----------------------------------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------+-------------+--------------------------------------------------------------+------------------------------+---------+---------------------------+-------+----------+----------------------------------------------------------------------------+
| 1 | SIMPLE | user | index_merge | PRIMARY,active,gender,age,private_photos,pictures_cnt,status | gender,private_photos,active | 4,1,2 | NULL | 28204 | 100.00 | Using intersect(gender,private_photos,active); Using where; Using filesort |
| 1 | SIMPLE | userext | eq_ref | userid | userid | 4 | db_name.user.id | 1 | 100.00 | Using index |
+----+-------------+---------+-------------+--------------------------------------------------------------+------------------------------+---------+---------------------------+-------+----------+----------------------------------------------------------------------------+
My question is why isn't the query using the index "status" 我的问题是为什么查询不使用索引“状态”
When I force it to use the index "status" - it takes 0.2s, if I don't it takes 2.5s 当我强制它使用索引“状态”时-需要0.2秒,如果我不这样做,则需要2.5秒
Any help much appreciated. 任何帮助,不胜感激。 regards.
问候。
u have several indexes that overlap the fields they index. 您有几个索引,它们与它们索引的字段重叠。 For example
pictures_cnt
and status
例如
pictures_cnt
和status
The optimizer "sees" your query as closer to use the fields of the pictures_cnt
rather than the status
index. 优化器将“查询”查询更接近地使用
pictures_cnt
的字段而不是status
索引。 If u will have more fields in the where
that belongs to the status
index, it might decide to use that index instead of picture_cnt
如果u在属于
status
索引的where
中将有更多字段,则可能决定使用该索引而不是picture_cnt
Do notice, it can't use both. 请注意,它不能同时使用。
If u think the optimizer is wrong (as is the case on uncommon occasions) u can force it to use the index u want it to use. 如果您认为优化器是错误的(在不常见的情况下就是这种情况),则可以强制其使用要使用的索引。 do benchmark it though.
进行基准测试。
After searching a bit, I found some recommendations regarding not using columns that allow null in indexes. 经过一番搜索,我发现了一些关于不使用允许索引为空的列的建议。 I changed the columns in the status index to all be non-null, and now that index is being used.
我将状态索引中的列都更改为非空,现在正在使用该索引。
As is usually the case, the simplest and cleanest solutions are the best. 通常,最简单,最干净的解决方案是最好的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.