“这是我参与8月更文挑战的第3天,活动详情查看:8月更文挑战”
前言
上一节,我们简单说了下mysql的索引,以及为什么like ‘%xx’会导致索引失效。总结来说就是一句话,‘%xx’破坏了索引值的有序性,因此优化器就决定放弃走树搜索功能。今天我们来探讨一下索引失效的另外一个原因,隐式类型转换。来一起究其所以然吧!
隐式类型转换
顾名思义,当两个类型不同的值进行比较时,需要转换成相同类型。而这一操作是mysql优化器来做的,所以被称之为隐式类型转换。那就又一个问题了,字符串和数字比较,到底是都转成字符串比较还是转成数字比较呢?咱们来实践一下。
同是数字类型相比较,结果是1。那如果‘10’>9或者10>‘9’的结果是都是1,则可以证明字符串和数字比较会把字符串转换成数字来比较。咱们实践证明一下。
实践证明真理,mysql的转换规则是,字符串转换成数字。
回归问题本身
先看例子,这张表的user_id是varchar类型的,所以建的索引也是字符串类型的。我们分别实践一下用字符串查询和数字查询的explain结果。
可以看出当用user_id = 123查询时,是全表扫描的。用上面说的mysql转换规则很好解释,user_id和123比较时,会先将user_id进行类型转换成数字在和123比较。等同于是
CAST(user_id AS signed int) = 123
代表在索引字段上做了函数操作,和like一样破坏了索引值的有序性,优化器自然不会选择走树索引功能。
那反过来呢?索引是int类型的,查询条件是字符串,会走索引么?我们来看phone这个字段的例子。
上面的例子理解的话,这个很好解释的。因为发生类型转换的不是索引字段,而是查询条件。相当于
phone = CAST('9898' AS signed int)
这样看是不是清晰很多,没有对索引字段做函数操作,自然是成功走索引的。
总结
like也好,函数操作也好,类型转换也好,导致索引失效的本质之一是破坏了索引值的有序性。所以大家在写sql的时候多用explain,总会有一些意外的发现!