MySQL该怎么给字符串字段加索引?(一)

这是我参与11月更文挑战的第15天,活动详情查看:2021最后一次更文挑战

前缀索引的使用

大家一定都了解登录的功能吧?很多登录功能都支持邮箱登录,那我们在后台一定会出现这么一条sql。 假设我们的表结构如下所示:

create table t_User(
 ID bigint unsigned primary key, 
 name varchar(64),
 email varchar(64),
 ...
 )engine=innodb;
复制代码

我们知道,如果我们没有给email字段添加索引,那这条sql一定会全盘扫描。所以我们给email添加索引,如下所示:

alter table t_User add index index1(email);
复制代码

创建的索引树将如下图所示:

截屏2021-11-17 下午10.35.36.png

我们执行这条SQL:

select x1 from t_User where email = '[email protected]'; 
复制代码
  • 当我们使用该index1索引时,引擎的执行顺序如下所示:

1.从index1 索引树找到满足索引是’[email protected]’的这条记录,取得 ID1 的值;

2.到主键上查到主键值是 ID1 的行,判断 email 的值是正确的,将这行记录加入结果集;

3.取index1索引树上刚刚查到的位置的下一条记录,发现已经不满足email='[email protected]’的条件了,循环结束。

这个过程中,只需要回主键索引取一次数据,所以系统认为只扫描了一行,我们只做一次回表的操作。

但是MySQL支持前缀索引,也就是说,我们可以把字符串的某一部分作为索引,如下所示:

alter table t_User add index index2(email(6));
复制代码

该语句取email字段的前6个字节作为索引。

创建的索引树将如下图所示:

截屏2021-11-17 下午10.37.37.png

很显然,取前6个字节作为索引的index2占用空间更少,但是可能会增加额外的扫描次数。

我们执行这条SQL:

select x1 from t_User where email = '[email protected]'; 
复制代码
  • 当我们使用index2索引时,引擎的执行顺序如下所示:
  1. 从 index2 索引树找到满足索引值是’budong’的记录,找到的第一个是 ID1;

  2. 到主键上查到主键值是 ID1 的行,判断出 email 的值不是’[email protected]’,这行记录丢弃;

  3. 取 index2 上刚刚查到的位置的下一条记录,发现仍然是’budong’,取出 ID2,再到ID索引上取整行然后判断,这次值对了,将这行记录加入结果集;

  4. 重复上一步,直到在 idxe2 上取到的值不是’budong’时,循环结束。

在这个过程中,要回主键索引取 4 次数据,也就是扫描了 4 行。所以我们发现,使用前缀索引后,导致我们读数据的次数变多了。

但如果我们定义的index2是email(9),那索引第一次取到的就会是‘budong112’,满足此前缀的只有一个,所以只要扫描一行就结束了。

小结

也就是说使用前缀索引,定义好长度,就可以做到既节省空间,又不用额外增加太多的查询 成本。

Guess you like

Origin juejin.im/post/7031552194012954654