MySQL 8.0 雖然發佈好久了,但可能你們都停留在 5.7.x,甚至更老,其實 MySQL 8.0 新增了許多重磅新特性,好比棧長今天要介紹的 "隱藏索引" 或者 "不可見索引"。html
隱藏索引 字面意思就是把索引進行隱藏,即不可見,它不是用來查詢優化的,因此它不會被優化器使用到。隱藏索引適用於除主鍵索引(顯示或者隱式設置)以外的索引,意味着主鍵索引是不能經過任何方式隱藏的。java
MySQL 數據庫默認建立的索引都是可見的,要顯式控制一個索引的可見性,能夠在 CREATE TABLE,CREATE INDEX 或 ALTER TABLE 的索引定義命令中使用 VISIBLE
或 INVISIBLE
關鍵字。mysql
以下面示例所示:面試
CREATE TABLE javastack ( age INT, weight INT, tall INT, INDEX age_idx (age) INVISIBLE ) ENGINE = InnoDB; CREATE INDEX weight_idx ON javastack (weight) INVISIBLE; ALTER TABLE javastack ADD INDEX tall_idx (tall) INVISIBLE;
要變動現有索引的可見性,能夠在 ALTER TABLE ... ALTER INDEX 命令中使用 VISIBLE
或 INVISIBLE
關鍵字。spring
年齡索引變動爲不可見(隱藏):sql
ALTER TABLE javastack ALTER INDEX age_idx INVISIBLE;
年齡索引變動爲可見:數據庫
ALTER TABLE javastack ALTER INDEX age_idx VISIBLE;
怎麼知道一個表中的索引是可見仍是不可見,能夠從 INFORMATION_SCHEMA.STATISTICS 表,或者 SHOW INDEX 命令輸出中得到。例如:intellij-idea
mysql> SELECT INDEX_NAME, IS_VISIBLE FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA = 'db1' AND TABLE_NAME = 'javastack'; +------------+------------+ | INDEX_NAME | IS_VISIBLE | +------------+------------+ | age_idx | YES | | weight_idx | NO | | tall_idx | NO | +------------+------------+
從上面隱藏索引介紹咱們知道,隱藏索引能夠不被優化器所使用,那麼咱們能夠把某個表的某個索引設置隱藏,而後再測試 SQL 語句的查詢性能。ide
便可以利用隱藏索引快速測試刪除索引後對 SQL 查詢性能的影響,而無需進行索引刪除、重建操做,若是須要該索引,再設置可見就行了,這在大表測試中無疑很是有用,由於對於大表索引的刪除和從新添加很耗性能,甚至影響表的正常工做。spring-boot
若是一個索引被設置成隱藏了,但實際上又須要被優化器所使用,有幾種表索引狀況缺失對查詢形成的影響:
1)SQL 查詢語句中包含了索引提示指向不可見索引會發生錯誤;
2)性能模式數據中顯示了受影響 SQL 查詢語句的負載增高;
3)SQL 查詢語句進行 EXPLIAN 時出現了不一樣的執行計劃;
4)SQL 查詢語句出如今了慢查詢日誌中(以前沒有出現);
系統變量 optimizer_switch 的 use_invisible_indexes 標誌的值,控制了優化器執行計劃構建時是否使用隱藏索引。
若是 use_invisible_indexes 值設置爲 off 關閉狀態(默認值),優化器默認會忽略隱藏索引,即和加入該參數以前的效果同樣。
若是 use_invisible_indexes 值設置爲 on 打開狀態,隱藏索引仍然保持不可見,但優化器會把隱藏索引加入到執行計劃的構建中。
若是想要在某條單個 SQL 查詢語句上啓用隱藏索引,可使用 SET_VAR 優化器提示來臨時更新 optimizer_switch 的值,以下所示:
mysql> EXPLAIN SELECT /*+ SET_VAR(optimizer_switch = 'use_invisible_indexes=on') */ > age, weight FROM javastack WHERE weight >= 150\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: javastack partitions: NULL type: range possible_keys: weight_idx key: weight_idx key_len: 5 ref: NULL rows: 2 filtered: 100.00 Extra: Using index condition mysql> EXPLAIN SELECT age, weight FROM javastack WHERE weight >= 150\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: javastack partitions: NULL type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 5 filtered: 33.33 Extra: Using where
索引的可見性不會影響索引的自身維護,例如,無論索引是可見仍是不可見,每次表數據行的更改索引都會更新,而且惟一索引也可防止插入重複數據。
沒有顯式主鍵的表若是在 NOT NULL 列上有任何一個惟一索引,則仍可能成爲有效的隱式主鍵。在這種狀況下,第一個這樣的索引會對錶數據行施加與顯式主鍵相同的約束,而且該索引不能設置爲不可見。
如如下表的定義:
CREATE TABLE javastack ( age INT NOT NULL, weight INT NOT NULL, UNIQUE weight_idx (weight) ) ENGINE = InnoDB;
該表定義不包含任何顯式主鍵,可是 weight 列爲 NOT NULL,在該列上建立的惟一索引在數據行上與主鍵具備相同的約束,而且不能使其不可見:
mysql> ALTER TABLE javastack ALTER INDEX weight_idx INVISIBLE; ERROR 3522 (HY000): A primary key index cannot be invisible.
假設如今咱們將一個顯式主鍵添加到表中:
ALTER TABLE javastack ADD PRIMARY KEY (age);
顯式主鍵不能設置爲不可見,此時,weight 列上的惟一索引再也不充當隱式主鍵,所以可使其設置不可見。
mysql> ALTER TABLE javastack ALTER INDEX weight_idx INVISIBLE; Query OK, 0 rows affected (0.03 sec)
本文介紹了 MySQL 8.0 中的新特性:隱藏(不可見)索引,這個索引並非新加的索引類型,而是能夠控制索引是否加入到執行計劃的構建之中。
在實際生產中也能夠利用隱藏索引進行 SQL 語句的性能測試,或者對索引進行邏輯刪除,以及索引的灰度發佈測試等,用處仍是蠻大的。
本次的分享就到這裏了,但願對你們有用。以爲不錯,在看、轉發分享一下哦~
最後,MySQL 系列教程還會繼續更新,關注Java技術棧公衆號第一時間推送,還能夠在公衆號菜單中獲取歷史 MySQL 教程,都是乾貨。
參考文檔:
https://dev.mysql.com/doc/ref...
話說大家用的 MySQL 哪一個版本呢?來投票一下!
另外,關注公衆號Java技術棧,在後臺回覆:面試,能夠獲取我整理的 MySQL 系列面試題和答案,很是齊全。
版權申明:本文系公衆號 "Java技術棧" 原創,原創實屬不易,轉載、引用本文內容請註明出處,禁止抄襲、洗稿,請自重,尊重他人勞動成果和知識產權。
近期熱文推薦:
1.Java 15 正式發佈, 14 個新特性,刷新你的認知!!
2.終於靠開源項目弄到 IntelliJ IDEA 激活碼了,真香!
3.我用 Java 8 寫了一段邏輯,同事直呼看不懂,你試試看。。
以爲不錯,別忘了隨手點贊+轉發哦!