盘点一下因为Mysql索引写的那些bug
关于索引,看起来简单
可是不要被它的表象迷惑了呀~~~
它的肚子里可不知道有多少弯弯道道呢,给你制造点小八哥的时候,你都要拍脑袋掐大腿,恍然大悟,“原来是它啊!!!”
1.like
like不用介绍,大家都明明白白的,就是做模糊搜索的吗,谁不知道呢~
产品经理说,我要模糊匹配,用户输一个字,只要带这个字的都给我展示出来,于是你就不管三七二十一,吭哧吭哧建个索引,不就是个like查询吗,so easy~~~
select a from test where a like '%c%'
2.这个就隐藏很深了,没写过这个bug,你都不会发现还有这么回事
select a from test where mobile=15387875676;//mobile 是varchar类型
以上,都会引起索引的失效,使得mysql进行全表扫描,性能大幅度下降。
究其原因,其实是最底层的索引数据结构的事,索引树就像一棵倒立着的大树,从根部到树杈,每个树杈还分小树杈,每个数据就是上面的树叶,按照一定的顺序,比如说按照编码的从小到大的顺序,从树根到树杈,从左边树杈到右边树杈,从小到大排列。然后拿着要查找的字符去这个树上查找数据(当然了,这个查找方式还会根据需求分深度遍历,广度遍历,这个就要另起一章讲了),按照前面的设定,从上到下,从左到右是按照从小到大的顺序排列,那么我们按照广度遍历去搜索要匹配的字符串,如果前面的字符串不确定(%c 这种形式),那就只能从头到尾走一遍查找满足条件的字符串了。如果说前面的字符串确定(c%),那我们可以大概知道要查询的字符串在哪个树杈上面,然后跳着搜索到要找的字符串。
2.mysql字段有类型,那在比较搜索的时候,需要把它们转换成同一类型的才可比较,那么当要搜索的数据类型和实际字段的类型不一致的时候,mysql是根据什么原则去转换然后判断的呢?
答案是将字符串转换成数字,可以在mysql客户端执行命令
select "10" > 9;//返回1,说明是将字符串转换成数字。
当执行2中的sql语句时,按照上面的规则,会将索引mobile转换成数字然后与数字 15387875676 比较判断是否相等,也就是会遍历mobile索引树,每个节点都转换后比较。
一共添加了21条测试数据,于是扫描了21条数据。
对比一下,如果将要查找的数据换成字符串类型:
select * from test where mobile='15387875676';
可以看到,只需要扫描一行数据。
先写这些,如果后面再遇到一些有意思的bug,再追加吧。