@TOC

系列文章

三、MySQL强人“锁”难《死磕MySQL系列 三》

四、S 锁与 X 锁的爱恨情仇《死磕MySQL系列 四》

五、如何抉择一般索引和惟一索引《死磕MySQL系列 五》

六、五分钟,让你明确MySQL是怎么抉择索引《死磕MySQL系列 六》

置信大多数小伙伴跟咔咔一样,给字符串增加索引从未设置过长度,明天就来聊聊如何正确的给字符串加索引。

一、如何建设索引

大多数零碎都会存在用户表,并且零碎初始设计应用了手机号码登录的。

这是产品提出了一个需要,让零碎也能够反对邮箱登录。

必定晓得的是若不给邮箱字段增加索引执行查问是会全表扫描。

此时你心里窃喜这还不简略,给邮箱字段加个索引完事呗!但要做到简单的需要做好,简略的需要要最好,加重所有对系统的压力。

此时的你拿起键盘就执行了alter table table_name add index idx_field (field)

有局部小伙伴不喜爱命令行创立索引,喜爱应用phpmyadmin工具来操作MySQL,那么在建设索引时有没有发现后边能够设置大小呢?

通过上边给大家展现的图片晓得字符串建设索引是能够定义长度的,那么两者有什么区别。

应用命令行alter table table_name add index idx_field (field)间接创立的索引默认是蕴含整个字符串。

若这样执行就指定了索引前缀长度alter table table_name add index idx_field (field(6))

一图解千愁,看一下建设的两个索引构造是什么样的。

索引一结构图

索引二结构图

从图中能够看到,指定了索引长度为6那么就只取邮箱字段的前6个字段,绝对索引蕴含整个字符串来说每个节点存储的数据会更多。

索引那篇文章也给大家说了建设索引在适合的范畴内越小越好。

万物皆两面,有坏就有好,第六期文章误选索引的因素之一就是扫描行数。

索引长度缩小带来的影响就是索引基数变大,从而减少额定的扫描记录数(执行explain的row字段)。

此时要执行select id,name,email from mac_user where email='1397393964@qq.com';

给整个字符串增加索引执行流程

1、从email索引树找到满足1397393964@qq.com的记录,失去主键ID为1

2、依据ID为1到主键索引树找到这条记录并判断email是否正确,将这行记录如果后果集。

3、反复第一步,直到不满足查问条件,循环完结。

指定索引长度执行流程

1、从email索引树找到满足139739的记录,失去主键ID为1

2、依据ID为1到主键索引树找到这条记录并判断email不正确,抛弃这行记录。

3、在email索引树找刚刚查问的下一条记录,发现还是139739,去除ID2,再到ID的索引树进行判断,当值对后退出后果集。

4、再持续反复上一步,直到不满足查问条件,循环完结。

论断

在模仿执行流程过程中很容易就发现,应用前缀索引会导致读取数据的次数减少,那是不是就代表应用前缀索引会减少查问代价呢?

必定不是的,试想此时定义的长度是6那么设置为7或者8呢!是不是会好很多,图中的案例为了不便设置了三个一样的数据,但理论状况根本不会呈现这样的状况。

建设索引关注的是区分度,只有区分度越高,反复值就越少,查问效率就越高。

所以应用前缀索引,只有定义好长度,就能够坐到既节俭空间,又不必额定减少太多的查问代价。

二、创立索引如何确定应用多长的前缀

MySQL中关键词distinct能够返回本列不同的后果集。

例如查问email列有多少个不同的值select count(distinct email) as num from mac_user。

如何计算列不同前缀有多少行

联合MySQL自带的函数left来实现,例如select count(distinct left (email,4)) as num4 from mac_user,截取email的前四个字符串计算有多少行。

再用这个值去除总数失去的就是比例,依据业务状况来判断多少比例能够。

三、应用前缀索引的影响

应用前缀索引会减少扫描行数,同时也会使笼罩索引生效。

为什么会影响笼罩索引?

若执行语句为select id,email from mac_user where email = '1397393964@qq.com'

应用整个字符串索引构造查问能够应用笼罩索引,从email索引获取到后果就间接返回了,不必再进行回表。

若应用前缀索引在email索引获取到后果后还须要回到id索引在查一下判断查问的email的值是否正确。

哪怕是设置了大于了email的长度也会回表再进行判断,因为MySQL并不知道定义的前缀是否截取了残缺信息。

论断

应用前缀索引会减少扫描行数,同样也应用不到笼罩索引。这个因素是你抉择是否应用前缀索引要思考的一个因素。

如果你不晓得应用前缀索引还是全字符串索引,本地进行测试选一个适合的计划上到生产环境即可。

四、如何把不能够变为能够应用

假如身份认证零碎存储的是身份证号,应该都晓得身份证号前6位是地址码,同县的身份证号前6位个别是一样的。

这样应用前缀索引的话区分度会非常低,岂但没有起到减速查问的作用,反而会造成索引区分度不大影响查问性能。

若把索引长度越长则每个节点寄存的索引值就越少,查问效率也会变的低效。

如果解决这种场景

第一种计划

存储数据时将数据顺叙存储,查问时在正序解决一下即可

第二种计划

在表中新增一个字段,存储数据的hash值,给hash增加前缀索引。

区别

应用这两种计划共同点都不反对范畴查问,都只能等值查问。

从占用空间来看:顺叙形式不会减少额定的存储空间,hash会减少一个字段。两者在空间并驾齐驱

从CPU耗费来看:顺叙须要应用函数reverse,hash须要应用crc32 ,reverse耗费会小

从查问效率来看:hash查问更稳固,crc32计算的值虽有抵触但概率十分小,根本每次查问的均匀扫描行数靠近1。而顺叙应用的前缀索引形式,还会减少扫描行数。

五、总结

间接给字符串创立占用空间。

创立前缀索引,节俭空间,会减少扫描行数,无奈应用笼罩索引。

顺叙存储,创立前缀索引解决区分度不大的问题。

应用hash形式,查问稳固,不反对范畴查问。

保持学习、保持写作、保持分享是咔咔从业以来所秉持的信念。愿文章在偌大的互联网上能给你带来一点帮忙,我是咔咔,下期见。