一個不留神,索引就創建重複了

相信沒有人會故意創建重複的冗餘的索引,很多重複和冗餘的索引都是在不經意間創建的,今天松哥來和大家捋一捋這個問題。

因爲我們日常在使用 MySQL 的過程中,基本上都是使用 InnoDB 引擎,所以接下來的討論主要是基於 InnoDB 引擎的 B+Tree 索引來討論,其他的哈希索引全文索引等不在討論範圍種。

1. 與聯合索引重複

在前面的文章中,松哥通過好幾篇文章和大家分享了聯合索引,包括它涉及到的覆蓋索引、前綴匹配等等,聯合索引好用,但是對聯合索引理解不到位的話,可能會創建出如下的重複索引:

CREATE TABLE `user2` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `address` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `password` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `email` varchar(16) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `user_index1` (`username`,`address`),
  KEY `user_index2` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

可以看到,這裏創建了兩個索引:

  • user_index1:這個索引包含兩個字段,username 在前 address 在後。
  • user_index2:這個索引包含一個字段 username。

其實 MySQL 中的 like 關鍵字也能用索引!一文中,松哥跟大家聊了索引的最左匹配原則,即:

(username,address) 索引既可以當成聯合索引來用,也可以通過最左匹配原則當成單獨的 (username) 索引來用。

所以,如果再爲 username 字段單獨創建一個索引就沒有必要了,這反而會導致增刪改的時候速度變慢。

不過怎麼說呢,上面這個結論適用於 99% 的場景,可能會有一些特殊情況,例如想把 (username) 和某一個特別長的字段建立一個聯合索引,此時如果單獨使用 username 字段進行搜索的話,效率可能降低,此時視搜索的重要程度,看是否需要創建一個重複的索引。

2. 主鍵加入聯合索引中

來看看下面這個索引:

CREATE TABLE `user2` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `address` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `password` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `email` varchar(16) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `user_index` (`username`,`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

一個名爲 user_index 的索引中包含了兩個字段 username 和 id,其中 id 是主鍵。

什麼是 MySQL 的“回表”?一文中,松哥和大家聊了,索引按照物理存儲方式可以分爲聚簇索引和非聚簇索引。

我們日常所說的主鍵索引,其實就是聚簇索引(Clustered Index);主鍵索引之外,其他的都稱之爲非主鍵索引,非主鍵索引也被稱爲二級索引(Secondary Index),或者叫作輔助索引。

對於主鍵索引和非主鍵索引,使用的數據結構都是 B+Tree,唯一的區別在於葉子結點中存儲的內容不同:

  • 主鍵索引的葉子結點存儲的是一行完整的數據。
  • 非主鍵索引的葉子結點存儲的則是主鍵值以及索引列的值。

這是兩者最大的區別。

既然主鍵已經存在於葉子結點中,那當然沒有在聯合索引中加入主鍵了。

好啦,幾個小小的注意點,希望能給小夥伴們啓發。

參考資料:

  • 《高性能 MySQL》
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章