(九)给字符加索引

场景:验证邮箱

mysql> create table SUser(
         ID bigint unsigned primary key, 
          email varchar(64),
           ... )engine=innodb;
mysql> select f1, f2 from SUser where email='xxx';

分析:

       1. 如果email上没有索引,那么将会做全盘扫描

       2.可以运用前缀索引(运用字符串的一部分作为索引);

分析比较:

mysql> alter table SUser add index index1(email); 
或
mysql> alter table SUser add index index2(email(6));
一个语句创建的 index1 索引里面,包含了每个记录的整个字符串;而第二个语句创建的 index2
索引里面,对于每个记录都是只取前 6 个字节。
从两图中你可以看到,由于 email(6) 这个索引结构中每个邮箱字段都只取前 6 个字节(即: zhangs ),所以占用的空间会更小,这就是使用前缀索引的优势。 但,这同时带来的损失是,可能会增加额外的记录扫描次数。
 

前缀索引查询步骤说明:

   1. 从index2索引树找到满足索引值是’zhangs’的记录,找到的第一个是ID1;
   2. 到主键上查到主键值是ID1的行,判断出email的值不是’[email protected]’,这行记录丢 弃;
   3. 取index2上刚刚查到的位置的下一条记录,发现仍然是’zhangs’,取出ID2,再到ID索引上取 整行然后判    断,这次值对了,  将这行记录加入结果集;
   4. 重复上一步,直到在idxe2上取到的值不是’zhangs’时,循环结束。

跟全盘扫描比较:

    1. 从index1索引树找到满足索引值是’[email protected]’的这条记录,取得ID2的值;
    2. 到主键上查到主键值是ID2的行,判断email的值是正确的,将这行记录加入结果集;
    3. 取index1索引树上刚刚查到的位置的下一条记录,发现已经不满足 email='[email protected]’的条件了,循环结束。

结论通过这个对比,你很容易就可以发现,使用前缀索引后,可能会导致查询语句读数据的次数变 多。

解决:又不全盘扫描,避免前缀索引的额外的增加的次数;

怎么解决:使用好前缀索引的话,定义好长度,就可以节省空间,又不用额外增加太多的查询成本;

使用前缀索引很可能会损失区分度,所以你需要预先设定一个可以接受的损失比例,比如 5%。然后,在返回的L4~L7中,找出不小于 L * 95%的值,假设这里L6、L7都满足,你就可以 选择前缀长度为6;

继续分析前缀索引:

    1.使用前缀索引,会增加扫描行数(但是创建长度够长的,又增加磁盘空间,数据页放下的数据记录就更少;但是要是减少索引长度,又会丧失索引的区分度,并且会反而不如全盘扫描);

    2.还有就是不能再使用覆盖索引;

所以要去寻找更好的增加索引办法:

   1.倒叙存储;

   2.使用hash字段;

倒叙存储:

    如果是身份证查询的haul,就把它倒过来查询,每次查询的时候这么写:

mysql> select field_list from t where id_card = reverse('input_id_card_string');
由于身份证号的最后 6 位没有地址码这样的重复逻辑,所以最后这 6 位很可能就提供了足够的区
分度。当然了,实践中你不要忘记使用 count(distinct) 方法去做个验证。

使用hash 字段:

你可以在表上再创建一 个整数字段,来保存身份证的校验码, 同时在这个字段上创建索引。
 
mysql> alter table t add id_card_crc int unsigned, 
       add index(id_card_crc);

mysql>select  field from t where id_card_crc=crc32('input_id_card') 
       and  id_card=id_input_id_card
这样,索引的长度变成了 4 个字节,比原来小了很多。
 
倒叙存储和使用hash字段增加索引的利弊:
 
1.
从占用的额外空间来看,倒序存储方式在主键索引上,不会消耗额外的存储空间,而 hash 字段方法需要增加一 个字段。当然,倒序存储方式使用 4 个字节的前缀长度应该是不够的,如 果再长 点,这个消耗跟额外这个 hash 字段也差不多抵消了。
2.
CPU 消耗方面,倒序方式每次写和读的时候,都需要额外调用一 reverse 函数,而 hash 字段的方式需要额外调用
crc32() 函数。如果只从这两个函数的计算复杂度来看的 话, reverse 函数额外消耗的 CPU 资源会更小些。
3.
从查询效率上看,使用 hash 字段方式的查询性能相对更稳定 些。因为 crc32 算出来的值虽 然有冲突的概率,但是概率非常小,可以认为每次查询的平均扫描行数接近 1 。而倒序存储 方式毕竟还是用的前缀索引的方式,也就是说还是会增加扫描行数。

   

发布了241 篇原创文章 · 获赞 31 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/qq_40406929/article/details/102958945
今日推荐