MySQL 联合索引

引言

用户表软删除,要保证手机号惟一且与已删除的用户不冲突,在数据库层面设置了UNIQUE联合索引。sql

image.png

在维基百科没找到联合索引比较官方的定义。数据库

通俗的解释:在某一列上加索引以提高相关语句查询效率,联合索引就是在多个列上加索引。segmentfault

联合索引

惟一性问题

执行如下语句新建test表用于演示:性能优化

CREATE TABLE `test` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) CHARACTER SET utf8 NOT NULL,
  `delete_at` bigint,
  PRIMARY KEY (`id`),
  UNIQUE KEY `UK2lcfdkjf5bcn2bs7kfwyjhr91` (`username`,`delete_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

执行语句,索引建立成功:工具

image.png

去表中新建两条数据为1-admin-102-admin-10,点击保存,会提示重复的admin-10违反了UK2lcfdkjf5bcn2bs7kfwyjhr91这个索引的UNIQUE约束,惟一索引生效。性能

image.png

NULL 问题

当把delete_at一列删除为NULL时,两条数据却能够保存成功。学习

image.png

联合索引会在有NULL值的状况下失效,因此应该避免联合索引中的字段值为NULL优化

完善的建表语句以下:spa

CREATE TABLE `test` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) CHARACTER SET utf8 NOT NULL,
  `delete_at` bigint DEFAULT 0 NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `UK2lcfdkjf5bcn2bs7kfwyjhr91` (`username`,`delete_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

最左匹配原则

为了提升查询效率,过去一直在username列上创建索引;那如今在usernamedelete_at两个字段上创建了联合索引,在执行如下语句的时候是否会有性能问题呢?code

SELECT * FROM test WHERE username = 'admin';

EXPLAIN分析如下这个语句,发现该语句的ExtraUsing index,说明本次查询是走索引的,而且就是联合索引UK2lcfdkjf5bcn2bs7kfwyjhr91

image.png

索引其实就是使用B+树进行排序,联合索引就是根据多个字段进行排序。

好比这里的usernamedelete_at的联合索引,先对username进行排序,username相同时,对delete_at进行排序,因此username绝对有序,delete_at相对有序。

因此根据username查询,彻底能够使用已经绝对有序的联合索引,而delete_at理论上就不能使用该索引。

总结

EXPLAIN工具在数据库学习与优化过程当中很重要,推荐学习:MySQL 性能优化神器 Explain 使用分析 - segmentfault

相关文章
相关标签/搜索