一、为什么需要使用前缀索引?
针对邮箱这样后缀都是 @xx.com 的字段,我们可以只存储前面的部分来减少索引的体积。这就是前缀索引
二、如何建立前缀索引?
创建索引时,我们可以指定某个索引值的长度,下面我们就创建了一个邮箱前六位组成的索引
alter table User add index index1(email(6));
三、使用前缀索引需要注意什么?
1. 前缀区分度
对于使用前缀索引的查询操作,mysql 在查询到索引之后,需要回到数据表中返回对应的值。如果值无法对应,则重新回到索引中寻找下一个值。
如果前缀区分度较低,就需要进行多次回表操作,增加了性能开销。而前缀过长,又增加了存储空间,失去了前缀索引原本的意义。
因此,我们需要合理定义好前缀索引的长度,使前缀索引值具备区分度。
解决方法
我们可以使用
select count(distinct left(email,4))as L4, count(distinct left(email,5))as L5, count(distinct left(email,6))as L6, count(distinct left(email,7))as L7,from User;
来统计取不同长度时,索引的区分度,找出不小于 email 数量*95% 的长度值,选择最小的作为我们前缀索引的长度。
2.不兼容覆盖索引
如果我们建立的索引中包含了 name、email 两个字段的全部信息,我们查询
select name,email from User Where email="xxx"
这时,mysql 会直接返回,而不需要进行任何回表操作。
如果我们此时,建立的是 name、email 的前缀索引。执行同样的查询操作时,mysql 会在前缀索引中找到符合的行,再回到数据表中进行验证,这样就多了一次回表操作。
四、相关优化思路
1.倒序索引
对于身份证号这样的数据,我们可以倒序存放数据,以此建立倒序索引
存储时,使用reverse()
进行倒序存储
select field_list from t where id_card = reverse('input_id_card_string')
2.hash
还是身份证号这样的问题,我们可以使用 hash 函数对身份证号码进行计算,插入记录时增加一个字段存储这个值,最后按照这个值进行查找。
不过这种方式需要注意判断 hash 冲突,防止出现误判的行为。
评论区