关于 Mysql 字段值分布很少的字段要不要加索引的问题.

我看到很多 mysql 索引的文章,都提到了,说如果某个字段的值分布范围很少(大量重复值),是不需要建立索引的.

但是我实际测试情况:

user_type_id字段有索引:

create table user_score_have_index
(
  id           int auto_increment
    primary key,
  score        int default '0'        not null,
  user_type_id tinyint(2) default '0' not null
);

create index user_score_have_index_score_index
  on user_score_have_index (score);

create index user_score_have_index_user_type_id_index
  on user_score_have_index (user_type_id);

user_type_id字段无索引:

create table user_score_no_index
(
  id           int auto_increment
    primary key,
  score        int default '0'        not null,
  user_type_id tinyint(2) default '0' not null
);

两张表数据一模一样, user_type_id 只有 1,2,3,4,5 五种值.

执行 explain 效果:

有索引:

clipboard.png

无索引:

clipboard.png

然后执行时间:

有索引用时 1s
无索引用时 6s

可以看到查询速度显著提高.

那么为什么还有这种说法呢?

阅读 8.6k
3 个回答

索引没有绝对的,要看索引是否能减少IO。
首先,在你的这个例子,很明显能用user_score_have_index_user_type_id_index来快速定位type=5的数据嘛,而且索引是有序的,也就是说,只需要定位到第一个type=5的数据,就可以顺着指针往右一直读了,比全表的离散读快很多哦。再说,对于id和type两个条件,user_score_have_index_user_type_id_index已经是覆盖索引了。(兄弟,索引名能不能短一点?)

常说的重复值多不适宜建索引,是考虑到回表的开销。

不是不需要加,是加了用处不大,这样看具体的场景,看表的扫描情况,而且1s和6s本身就不是“显著提高”,又不是几十倍,如果不是count,而且获取几条数据,你这个索引就没什么用了,对于这么大的数据你不能直接获取count,应该再其他地方单独存储,请求几次数据库就挂了,你只不过正好碰到count有用而已,大部分情况下效果不佳

MySQL索引原理及慢查询优化

脱离实际业务谈优化都是耍流氓
上面回复已经提到的就不再说了 就补充一条
我问你如果一语句访问十分频繁,但是有大量重复 你加不加?

推荐问题
宣传栏