MySQL 中区分度小的组合索引问题

2018-09-27 17:22:22 +08:00
 hzj629206

有 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 上建索引,则效率正常,很快。

有人能解释这是什么原理吗?

3958 次点击
所在节点    MySQL
8 条回复
GTim
2018-09-27 18:08:23 +08:00
吐槽下 3000 0000,写法难道不是 30 000 000。

between to 是哪个数据库的语法

如果使用的是 MySQL,可以在前面添加 explain 就知道了。

楼主,在 update_time 的情况下 status 就是一个废物。update_time 可以说是除了主键之外离散度最高的。

因为没有其它信息,我猜,是因为引擎发现 status 的离散度不高,直接使用全表扫描了
hzj629206
2018-09-27 18:41:15 +08:00
@GTim
between xx and yy. sorry 写错了。

explain 结果是使用 idx_status,也使用 FORCE INDEX(idx_status)试过了,应该是使用了这个索引的。

我的疑问是单独用 update_time 是可行的,但目前存在的(status, update_status)问题出在哪里?
littlewing
2018-09-27 19:35:37 +08:00
因为优化器发现 status 值太少了,选择使用全表扫描。可以试一下 force index?
建议单独为 update_time 建一个索引
zjp
2018-09-27 19:52:36 +08:00
换成 (update_time, status) 试试。不管怎样执行 EXPLAIN 再说,光猜没用
Raymon111111
2018-09-27 20:39:43 +08:00
因为用啥索引是靠猜的

因为建了太多无用的索引导致猜错了

force index 一下吧
sagaxu
2018-09-27 23:22:30 +08:00
之前试过组合索引(a, b),a 是值域为 0-2 的 int 类型,b 是分布稀疏的 int 类型,单表 1 亿条数据,数据 20 多 g,索引 2g 多,使用 a=0 and b between 1000 and 2000 做条件,结果集条数几百,查询速度是豪秒级。

所以这不是区分度的问题
xidianlz
2018-09-28 10:44:51 +08:00
额 感觉题主是不是什么地方设置错了,首先理论上不会这样,其次我自己造了一千万的数据,也没复现这种情况
encro
2018-09-28 14:56:31 +08:00
status=xx,单 xx 的值接近一半时,自动使用全表扫描好像会。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/493252

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX