暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MYSQL索引(二)

BearKang 2021-05-07
775

MYSQL索引

了解了主键索引和普通索引之后, 今天认识一下联合索引。测试表User里有id,name,address,supply_apply_id,is_delete字段,索引有主键id,name索引和name,address联合索引,数据量200万。

覆盖索引

如上图,为了保证能够分别按照name和name,address索引查询满足条件的100条数据,sql里显示使用了force index手动选择索引,慢查询日志显示name索引效率要低于name,address索引,这就是因为我们需要查询的id,name,address信息在联合索引中都有保存,而在name索引中信息不全,需要回表才能得到剩余的信息,而这个效率的差距会随着回表数据的次数增加而增加,通过联合索引来减少回表次数而有效提升查询效率,叫做覆盖索引

最左原则

最左匹配原则就是按照索引的组织顺序,如果查询条件可以按照顺序组织,则可以使用最左匹配到的最后的字段的所有索引,也可以是字符串的最左N个字符。上图执行计划的key_len显示为1023,代表只使用了一个字段name,接下来再执行explan select id, name , address from user where name >= FUYDUDHSBDHS and address > FUYDUDHSBDHS limit 100 可以看到 ken_len 变成了2046, 代表用上了name,address两个字段的索引,原因是在name条件中加了=条件,而在相等的name里,address是局部有序的,因此这一部分是可以用上address的有序性的。

索引下推

索引下推是指mysql在回表之前,根据已有信息判断是否满足where条件过滤,如果不满足就不取这一行数据,从而减少回表次数,来提升效率。现在的表大都是用逻辑删除,因此查询普遍都会带上本身的where过滤条件之后附加一个is_delete = 0,我一度困惑是否需要在每一个索引上附加上该字段以便使用下推的特性,因为考虑到添加上的内存开销和预期收益,很难决策,直到现在还是没有一个明确的界定方式。我认为如果一张表的逻辑删除很少的情况下,索引不需要添加逻辑删除字段,而在删除比较频繁的场景需要添加该字段,因为在删除场景较少的情况下下推情况下是在二级索引发现没有删除然后回表取行数据,和不下推情况先回表然后发现没有删除再取行数据性能无差。而在删除场景较多比如name=abc的100行数据都已被删除,在下推场景二级索引判断100行全被删除,都不会回表,而非下推场景需要回表100次然后发现都被删除掉,耗费大量时间。所以删除场景多的情况下索引加上逻辑删除是可以取得较大收益的。下图是我删除了接近一半数据后的查询未删除数据的慢查询日志,可以看到使用下推的效率接近是非下推的2倍。


总结

ken_len计算方式utf8mb4 255 * 4 + 1 + 2 = 1023,可变长字符utf8系数为3,utf8mb4为4,1为可以为null标记,2为可变长字符。通常可能的索引失效情况包括:字段类型隐式转换并且是将索引字段转换成匹配条件字段类型,索引字段上做函数运算违反最左匹配原则, 遵守最左匹配原则但是匹配过程中使用了范围查询之后,索引只到范围查询处有效,除了开头例子的=这一段, 使用 != 判断,使用sysdate()时间函数。索引加快查询速度的根本原因是利用索引的有序性,而索引失效的根本原因也是破坏了有序性,其中sysdate函数失效原因是它是在sql执行时才动态获取系统时间。


文章转载自BearKang,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论