用戶表軟刪除,要保證手機號惟一且與已刪除的用戶不衝突,在數據庫層面設置了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