關於 MySQL 8.0 新特性“隱藏索引”的一點思考

MySQL 8.0有一個稱爲“隱藏索引”的新功能,它允許快速啓用/禁用MySQL Optimizer使用的索引。

在此分享一些對這個新功能的首次使用經驗和想法。

對我們有什麼用?

一是如果你想刪除一個索引,但又想事先知道效果。你就可以使它對優化程序不可見。這是一個快速的元數據更改,使索引不可見。一旦確定沒有性能下降,就可以真正去刪除索引。

關鍵的一點是,隱藏索引不能供優化器使用,但它仍然存在,並通過寫入操作保持最新。即便我們嘗試“FORCE INDEX”,優化器也不會使用它,雖然我認爲我們應該能夠在某種程度上強制它。可能會有這樣的情況:

  1. 我們可以創建一個新的隱形索引,但如果想要測試它,必須使它可見。這意味着所有對應用程序有即時影響的查詢都將能夠使用它。如果目的只是想測試它,我不認爲這是最好的方法,不是所有人的服務器上都有相同的數據大小和真實數據。強制隱藏索引這時候可能會很有用。

  2. 你有許多索引,但不確定哪一個未使用。你可以將一個索引更改爲不可見,以查看是否存在任何性能下降。如果是,你可以立即更改。

  3. 你可能有一個特殊情況,只有一個查詢可以使用該索引。在這種情況下,隱藏索引可能是一個很好的解決方案。

怎麼創建隱藏索引

有兩個選項。 我們可以創建一個具有隱藏索引的表,如下所示:

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]

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