MySQL 该不该给 status 添加索引?

2020-04-28 18:47:02 +08:00
 zealinux

现在某个表,有个 status,有两个值,0,1

按照好多文档说明,这列不应该加索引。

比如,0 是未处理的,1 是处理过的。

一般都是要查 0,来进行处理。

发现 status 加了索引之后,查找的速度飞快。

2000w 的表,SELECT COUNT(*), 从 14s 下降到 0.1s 以下( SQL_NO_CACHE )

5888 次点击
所在节点    MySQL
28 条回复
uxff
2020-04-28 22:23:15 +08:00
看了 mysql 的实现原理后,你就懂了,mysql innodb 索引是针对现代磁盘高度优化的。只统计或查询索引上的字段都会快很多。
littlewing
2020-04-28 23:24:18 +08:00
count(*) count(1) count(status) 确实是有用的,因为 MySQL 判断扫描 status 索引也能得到正确的 count,而 status 索引比其他索引和主键索引扫描起来快多了
但是如果想用 status 索引加快 select * from xxx where status = 1 这样的查找速度的话,就不用想了,MySQL 绝对会选择扫描主键索引,因为 cardinality 太小了,再加上回表的开销,MySQL 会认为走主键索引更快
littlewing
2020-04-28 23:25:54 +08:00
@xinshoushanglu innodb 是不能这样做的,因为有事务和隔离级别的存在,同一时间不同事务看到的 count 可以不一样,Myisam 是可以这样做的
hooopo
2020-04-29 00:34:18 +08:00
具体情况具体分析
thinkmore
2020-04-29 16:54:37 +08:00
不建议加。status 区分度太低了,基本全是扫描叶子节点。

如果你查这样的,你就能感受到了

select column_1,column_2,column_3 from table where status = 1
qyvlik
2020-04-29 23:06:10 +08:00
根据业务要求加,就是根据哪种 sql 查询多的去加索引,还要根据具体 sql 查询拼接的条件。
所谓 status 区分度低的前提是 0,1 均匀分布,说白了可能各 50%,这样加索引就没啥效果。按照你的问题描述,以及可能的常用场景,0 和 1 的分布不是均匀的,一般是 0 >> 1,就是说 status 为 0 可能就是全表记录的 一小部分(例如 1%),那么如下的查询 sql:
select * from table where status = 0
就会走索引,而且索引扫描的行数也不会太多。
但是如下的 sql:
select * from table where status = 1,可能会走索引,但是扫描的行数过多时会让 mysql 做出扫描全表的执行计划。
select count(*) from table,在有索引的情况,可能会走索引,具体看看执行计划。
54qyc
270 天前
status 如果是和常量值比较,并且常量值占比比较小,则 mysql 会走索引而不会全表扫描. 这里和 count 机制没关系吧,select 任意的速度应该都会更快。OP 是这样吗?
54qyc
270 天前
@littlewing 并不是这样。与常量比较,mysql 会看 1 的占比。占比低就会走索引。而不是看基数,看基数发生在与列值比较的情况。

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

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

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

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

© 2021 V2EX