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

相關文章
相關標籤/搜索