https://juejin.cn/post/6992912997580537870

前言

上一节,我们简单说了下mysql的索引,以及为什么like ‘%xx’会导致索引失效。总结来说就是一句话,‘%xx’破坏了索引值的有序性,因此优化器就决定放弃走树搜索功能。今天我们来探讨一下索引失效的另外一个原因,隐式类型转换。来一起究其所以然吧!

隐式类型转换

顾名思义,当两个类型不同的值进行比较时,需要转换成相同类型。而这一操作是mysql优化器来做的,所以被称之为隐式类型转换。那就又一个问题了,字符串和数字比较,到底是都转成字符串比较还是转成数字比较呢?咱们来实践一下。

https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b3900fee2b3c4d45aa22dd1fe0ea05dd~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp

同是数字类型相比较,结果是1。那如果‘10’>9或者10>‘9’的结果是都是1,则可以证明字符串和数字比较会把字符串转换成数字来比较。咱们实践证明一下。

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e962b140bc984b54b55437cee9900263~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp

https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e2e1a1c47048437a8fc8c76f4d529125~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp

实践证明真理,mysql的转换规则是,字符串转换成数字

回归问题本身

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/cebbe3bcc05a43078c766af9e6a79c48~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp

先看例子,这张表的user\_id是varchar类型的,所以建的索引也是字符串类型的。我们分别实践一下用字符串查询和数字查询的explain结果。

https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5e7cff11455d4b548d3445ccc7236603~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp

可以看出当用user\_id = 123查询时,是全表扫描的。用上面说的mysql转换规则很好解释,user\_id和123比较时,会先将user\_id进行类型转换成数字在和123比较。等同于是

CAST(user\_id AS signed int) = 123

代表在索引字段上做了函数操作,和like一样破坏了索引值的有序性,优化器自然不会选择走树索引功能。

那反过来呢?索引是int类型的,查询条件是字符串,会走索引么?我们来看phone这个字段的例子。

https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c1a5cfb8df3f446abc20e76e68593cc8~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp