用户表软删除,要保证手机号惟一且与已删除的用户不冲突,在数据库层面设置了UNIQUE
联合索引。sql
在维基百科没找到联合索引比较官方的定义。数据库
通俗的解释:在某一列上加索引以提高相关语句查询效率,联合索引就是在多个列上加索引。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;
执行语句,索引建立成功:工具
去表中新建两条数据为1-admin-10
和2-admin-10
,点击保存,会提示重复的admin-10
违反了UK2lcfdkjf5bcn2bs7kfwyjhr91
这个索引的UNIQUE
约束,惟一索引生效。性能
当把delete_at
一列删除为NULL
时,两条数据却能够保存成功。学习
联合索引会在有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
列上创建索引;那如今在username
和delete_at
两个字段上创建了联合索引,在执行如下语句的时候是否会有性能问题呢?code
SELECT * FROM test WHERE username = 'admin';
用EXPLAIN
分析如下这个语句,发现该语句的Extra
为Using index
,说明本次查询是走索引的,而且就是联合索引UK2lcfdkjf5bcn2bs7kfwyjhr91
。
索引其实就是使用B+
树进行排序,联合索引就是根据多个字段进行排序。
好比这里的username
与delete_at
的联合索引,先对username
进行排序,username
相同时,对delete_at
进行排序,因此username
绝对有序,delete_at
相对有序。
因此根据username
查询,彻底能够使用已经绝对有序的联合索引,而delete_at
理论上就不能使用该索引。
EXPLAIN
工具在数据库学习与优化过程当中很重要,推荐学习:MySQL 性能优化神器 Explain 使用分析 - segmentfault