前言
最近通过 https://zbov.meizu.com/ 平台推送的’SLOW_QUERY’做相应的优化,在变更前,我会和开发沟通下优化选择,然后根据业务情况再做相应的优化。发现对于索引选择性,大家还是看法不一的。所以就写了这篇文章。
什么是索引选择性
当我们设计索引的时候首先一个就是字段基数问题,如果一个字段在100万行数据里面,这100万行数据中这个字段的值,要不然是0,要不然就是1,那么这个字段的基数就是2,为什么?因为这个字段的值就两个选择,0/1。这个时候我们就称这种字段的区分度不高,也就是索引选择性差。如果在这种字段上建立索引,索引树中就只有0/1两种值,进行二分查找会有怎样的体验可想而知。
所以说我们一般建立索引的时候会尽可能的选择那些基数比较大的字段,也就是索引选择性比较好的字段
是不是索引选择性低的字段,就不适合创建索引或者成为联合索引的一部分?
拿两个线上的真实案例来讲
- a_col 字段索引选择性要远好于 b_col
案例1
当 a_col = 1 匹配的记录数有 100w 条,而符合 b_col = 2 的记录数只有 5 条。
那么如果我们只对索引选择性好的字段 a_col 建立索引 IDX_a(a_col),那么通过 IDX_a 找到符合的 100w 条记录后,还要在这些数据逐一去对比 b_col = 2 的数据,这样会导致不必要的过滤。
如果我们创建联合索引 IDX_a_b(a_col,b_col) ,直接通过 IDX_a_b 定位到 b_col = 2 的 5 条数据,就不需要额外的过滤了。这样明显提升了查询的速度。
案例2
当 a_col = 1 匹配的记录数有 100 条,而符合 b_col = 2 的记录数只有 5 条。
这时我们通过 IDX_a 找到符合的 100 条记录后,再去定位 b_col = 2 的 5 条数据,其实消耗的时间并不大。
小结
- 一般建立索引,尽量使用那些基数比较大的字段,就是值比较多的字段,那么才能发挥出B+树快速二分查找的优势来。
- 创建索引的目的是尽可能快速的找到符合 where 条件的行,减少回表。
- 索引选择性低的字段并不是不可以建立索引,在联合索引中,我们要结合业务 + SQL,真正符合条件的记录是多少。基数越小,查询越快。