MySQL 8.0有一個稱爲「隱藏索引」的新功能,它容許快速啓用/禁用MySQL Optimizer使用的索引。html
在此分享一些對這個新功能的首次使用經驗和想法。mysql
對咱們有什麼用?sql
一是若是你想刪除一個索引,但又想事先知道效果。你就能夠使它對優化程序不可見。這是一個快速的元數據更改,使索引不可見。一旦肯定沒有性能降低,就能夠真正去刪除索引。服務器
關鍵的一點是,隱藏索引不能供優化器使用,但它仍然存在,並經過寫入操做保持最新。即使咱們嘗試「FORCE INDEX」,優化器也不會使用它,雖然我認爲咱們應該可以在某種程度上強制它。可能會有這樣的狀況:ide
咱們能夠建立一個新的隱形索引,但若是想要測試它,必須使它可見。這意味着全部對應用程序有即時影響的查詢都將可以使用它。若是目的只是想測試它,我不認爲這是最好的方法,不是全部人的服務器上都有相同的數據大小和真實數據。強制隱藏索引這時候可能會頗有用。性能
你有許多索引,但不肯定哪個未使用。你能夠將一個索引更改成不可見,以查看是否存在任何性能降低。若是是,你能夠當即更改。測試
你可能有一個特殊狀況,只有一個查詢能夠使用該索引。在這種狀況下,隱藏索引多是一個很好的解決方案。優化
怎麼建立隱藏索引url
有兩個選項。 咱們能夠建立一個具備隱藏索引的表,以下所示:spa
CREATE TABLE `t1` ( `i` int(11) DEFAULT NULL, `j` int(11) DEFAULT NULL, `k` int(11) DEFAULT NULL, KEY `i_idx` (`i`), KEY `idx_1` (`i`,`j`,`k`) INVISIBLE ) ENGINE=InnoDB DEFAULT CHARSET=latin1
或者咱們能夠使用alter table並將索引更改成隱藏:
ALTER TABLE t1 ALTER INDEX idx_1 INVISIBLE;
怎麼使用隱藏索引
若是咱們如今要刪除索引,咱們能夠將其更改成隱藏。 可是使用「FORCE / USE INDEX」的查詢怎麼樣? 他們是否會拋出一個錯誤? 若是強制不存在的索引,你會收到錯誤。 你不會看到隱藏索引的錯誤。 優化器不會使用它,但知道它存在。
show create table t1 G *************************** 1. row *************************** Table: t1 Create Table: CREATE TABLE `t1` ( `i` int(11) DEFAULT NULL, `j` int(11) DEFAULT NULL, `k` int(11) DEFAULT NULL, KEY `i_idx` (`i`), KEY `idx_1` (`i`,`j`,`k`) ) ENGINE=InnoDB DEFAULT CHARSET=latin11 row in set (0.00 sec) mysql> explain select * from t1 force index(idx_1) where i=1 and j=4; +----+-------------+-------+------------+------+---------------+-------+---------+-------------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+-------+---------+-------------+------+----------+-------------+ | 1 | SIMPLE | t1 | NULL | ref | idx_1 | idx_1 | 10 | const,const | 2 | 100.00 | Using index | +----+-------------+-------+------------+------+---------------+-------+---------+-------------+------+----------+-------------+1 row in set, 1 warning (0.00 sec) mysql> alter table t1 alter index idx_1 invisible; Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0mysql> explain select * from t1 force index(idx_1) where i=1 and j=4; +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+ | 1 | SIMPLE | t1 | NULL | ALL | NULL | NULL | NULL | NULL | 16 | 6.25 | Using where | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+1 row in set, 1 warning (0.01 sec) mysql> explain select * from t1 where i=1 and j=4; +----+-------------+-------+------------+------+---------------+-------+---------+-------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+-------+---------+-------+------+----------+-------------+ | 1 | SIMPLE | t1 | NULL | ref | i_idx | i_idx | 5 | const | 2 | 10.00 | Using where | +----+-------------+-------+------------+------+---------------+-------+---------+-------+------+----------+-------------+1 row in set, 1 warning (0.00 sec)
正如你所看到的,若是咱們使用帶有隱藏索引的「FORCE INDEX」,MySQL會執行全表掃描。 MySQL不會拋出任何錯誤,由於索引存在,但它不可見。 即便有另外一個可用的索引,它也將執行全表掃描。 在大型表上,這可能會致使嚴重的性能問題。 即便MySQL在查詢執行期間不拋出任何錯誤,它也應該會在錯誤日誌中記錄一個警告。
結論
我認爲隱形索引是一個偉大的新功能,能夠對許多人有用。 若是有須要,能夠嘗試着去使用,而且嘗試記錄試圖使用隱藏索引的查詢,說不定會獲得一些驚喜。
英文原文:Thoughts on MySQL 8.0's Invisible Indexes
文章轉載自 開源中國社區 [http://www.oschina.net]