场景:验证邮箱
分析:
1. 如果email上没有索引,那么将会做全盘扫描
2.可以运用前缀索引(运用字符串的一部分作为索引);
分析比较:
第 一个语句创建的 index1 索引里面,包含了每个记录的整个字符串;而第二个语句创建的 index2
索引里面,对于每个记录都是只取前 6 个字节。


从两图中你可以看到,由于 email(6) 这个索引结构中每个邮箱字段都只取前 6 个字节(即: zhangs ),所以占用的空间会更小,这就是使用前缀索引的优势。 但,这同时带来的损失是,可能会增加额外的记录扫描次数。
前缀索引查询步骤说明:
1. 从index2索引树找到满足索引值是’zhangs’的记录,找到的第一个是ID1;
2. 到主键上查到主键值是ID1的行,判断出email的值不是’zhangssxyz@’,这行记录丢 弃;
3. 取index2上刚刚查到的位置的下一条记录,发现仍然是’zhangs’,取出ID2,再到ID索引上取 整行然后判 断,这次值对了, 将这行记录加入结果集;
4. 重复上一步,直到在idxe2上取到的值不是’zhangs’时,循环结束。
跟全盘扫描比较:
1. 从index1索引树找到满足索引值是’zhangssxyz@’的这条记录,取得ID2的值;
2. 到主键上查到主键值是ID2的行,判断email的值是正确的,将这行记录加入结果集;
3. 取index1索引树上刚刚查到的位置的下一条记录,发现已经不满足 email='zhangssxyz@’的条件了,循环结束。
结论:通过这个对比,你很容易就可以发现,使用前缀索引后,可能会导致查询语句读数据的次数变 多。
解决:又不全盘扫描,避免前缀索引的额外的增加的次数;
怎么解决:使用好前缀索引的话,定义好长度,就可以节省空间,又不用额外增加太多的查询成本;
使用前缀索引很可能会损失区分度,所以你需要预先设定一个可以接受的损失比例,比如 5%。然后,在返回的L4~L7中,找出不小于 L * 95%的值,假设这里L6、L7都满足,你就可以 选择前缀长度为6;
继续分析前缀索引:
1.使用前缀索引,会增加扫描行数(但是创建长度够长的,又增加磁盘空间,数据页放下的数据记录就更少;但是要是减少索引长度,又会丧失索引的区分度,并且会反而不如全盘扫描);
2.还有就是不能再使用覆盖索引;
所以要去寻找更好的增加索引办法:
1.倒叙存储;
2.使用hash字段;
倒叙存储:
如果是身份证查询的haul,就把它倒过来查询,每次查询的时候这么写:
由于身份证号的最后 6 位没有地址码这样的重复逻辑,所以最后这 6 位很可能就提供了足够的区
分度。当然了,实践中你不要忘记使用 count(distinct) 方法去做个验证。
使用hash 字段:
你可以在表上再创建一 个整数字段,来保存身份证的校验码, 同时在这个字段上创建索引。
这样,索引的长度变成了 4 个字节,比原来小了很多。
倒叙存储和使用hash字段增加索引的利弊:
1.
从占用的额外空间来看,倒序存储方式在主键索引上,不会消耗额外的存储空间,而 hash 字段方法需要增加一 个字段。当然,倒序存储方式使用 4 个字节的前缀长度应该是不够的,如 果再长 点,这个消耗跟额外这个 hash 字段也差不多抵消了。
2.
在 CPU 消耗方面,倒序方式每次写和读的时候,都需要额外调用一 次 reverse 函数,而 hash 字段的方式需要额外调用 一
次 crc32() 函数。如果只从这两个函数的计算复杂度来看的 话, reverse 函数额外消耗的 CPU 资源会更小些。
3.
从查询效率上看,使用 hash 字段方式的查询性能相对更稳定 一 些。因为 crc32 算出来的值虽 然有冲突的概率,但是概率非常小,可以认为每次查询的平均扫描行数接近 1 。而倒序存储 方式毕竟还是用的前缀索引的方式,也就是说还是会增加扫描行数。
















