有 idx_status (status, update_time)
status 就是有限的状态值 update_time 是 unix timestamp 的整数值
现在 3000 0000 表中,select * from tbl where status = xx and update_time between yy to zz.
效率很低。
status 区分度小这个都知道,如果只有 idx_status (status),这显然会很慢。 但不明白(status, update_time)为什么也慢?
单独在 update_time 上建索引,则效率正常,很快。
有人能解释这是什么原理吗?
1
GTim 2018-09-27 18:08:23 +08:00 1
吐槽下 3000 0000,写法难道不是 30 000 000。
between to 是哪个数据库的语法 如果使用的是 MySQL,可以在前面添加 explain 就知道了。 楼主,在 update_time 的情况下 status 就是一个废物。update_time 可以说是除了主键之外离散度最高的。 因为没有其它信息,我猜,是因为引擎发现 status 的离散度不高,直接使用全表扫描了 |
2
hzj629206 OP @GTim
between xx and yy. sorry 写错了。 explain 结果是使用 idx_status,也使用 FORCE INDEX(idx_status)试过了,应该是使用了这个索引的。 我的疑问是单独用 update_time 是可行的,但目前存在的(status, update_status)问题出在哪里? |
3
littlewing 2018-09-27 19:35:37 +08:00
因为优化器发现 status 值太少了,选择使用全表扫描。可以试一下 force index?
建议单独为 update_time 建一个索引 |
4
zjp 2018-09-27 19:52:36 +08:00
换成 (update_time, status) 试试。不管怎样执行 EXPLAIN 再说,光猜没用
|
5
Raymon111111 2018-09-27 20:39:43 +08:00
因为用啥索引是靠猜的
因为建了太多无用的索引导致猜错了 force index 一下吧 |
6
sagaxu 2018-09-27 23:22:30 +08:00 via Android
之前试过组合索引(a, b),a 是值域为 0-2 的 int 类型,b 是分布稀疏的 int 类型,单表 1 亿条数据,数据 20 多 g,索引 2g 多,使用 a=0 and b between 1000 and 2000 做条件,结果集条数几百,查询速度是豪秒级。
所以这不是区分度的问题 |
7
xidianlz 2018-09-28 10:44:51 +08:00
额 感觉题主是不是什么地方设置错了,首先理论上不会这样,其次我自己造了一千万的数据,也没复现这种情况
|
8
encro 2018-09-28 14:56:31 +08:00
status=xx,单 xx 的值接近一半时,自动使用全表扫描好像会。
|