死磕mysql系列 七|字符串可以这样加索引,你知吗?《死磕MySQL系列 七》( 二 )


建立索引关注的是区分度 , 只有区分度越高 , 重复值就越少 , 查询效率就越高 。
所以使用前缀索引 , 只要定义好长度 , 就可以坐到既节省空间 , 又不用额外增加太多的查询代价 。
二、创建索引如何确定使用多长的前缀MySQL中关键词distinct可以返回本列不同的结果集 。
例如查询email列有多少个不同的值select count(distinct email) as num from mac_user 。
如何计算列不同前缀有多少行
结合MySQL自带的函数left来实现 , 例如select count(distinct left (email4)) as num4 from mac_user , 截取email的前四个字符串计算有多少行 。
再用这个值去除总数得到的就是比例 , 根据业务情况来判断多少比例可以 。
三、使用前缀索引的影响使用前缀索引会增加扫描行数 , 同时也会使覆盖索引失效 。
为什么会影响覆盖索引?
若执行语句为select idemail 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方式 , 查询稳定 , 不支持范围查询 。


【死磕mysql系列 七|字符串可以这样加索引,你知吗?《死磕MySQL系列 七》】坚持学习、坚持写作、坚持分享是咔咔从业以来所秉持的信念 。 愿文章在偌大的互联网上能给你带来一点帮助 , 我是咔咔 , 下期见 。