原文地址:MySQL 8.0 Reference Manual
我在慕课网发布的免费视频讲解 MySQL 8.0 版本新特性。
MySQL 8.0 支持隐藏索引(invisible index),也称为不可见索引。隐藏索引不会被优化器使用。主键不能设置为隐藏(包括显式设置或隐式设置)。
索引默认是可见的(visible)。使用CREATE TABLE
、CREATE INDEX
或ALTER TABLE
语句的VISIBLE
或者INVISIBLE
选项设置一个新建索引的可见性:
CREATE TABLE t1 (
i INT,
j INT,
k INT,
INDEX i_idx (i) INVISIBLE
) ENGINE = InnoDB;
CREATE INDEX j_idx ON t1 (j) INVISIBLE;
ALTER TABLE t1 ADD INDEX k_idx (k) INVISIBLE;
使用ALTER TABLE ... ALTER INDEX
语句的VISIBLE
或者INVISIBLE
选项修改已有索引的可见性:
ALTER TABLE t1 ALTER INDEX i_idx INVISIBLE;
ALTER TABLE t1 ALTER INDEX i_idx VISIBLE;
通过数据字典表 INFORMATION_SCHEMA.STATISTICS 或者SHOW INDEX
命令可以查看索引的可见性。例如:
mysql> SELECT INDEX_NAME, IS_VISIBLE
FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = 'db1' AND TABLE_NAME = 't1';
+------------+------------+
| INDEX_NAME | IS_VISIBLE |
+------------+------------+
| i_idx | YES |
| j_idx | NO |
| k_idx | NO |
+------------+------------+
不可见索引特性可以用于测试删除某个索引对于查询性能的影响,同时又不需要真正删除索引,也就避免了错误删除之后的索引重建。对于一个大表上的索引进行删除重建将会非常耗时,而将其设置为不可见或可见将会非常简单快捷。
如果某个设置为隐藏的索引实际上仍然需要或者被优化器所使用,可以通过以下多种方法发现缺少该索引带来的影响:
系统变量 optimizer_switch 的 use_invisible_indexes 值控制了优化器构建执行计划时是否使用隐藏索引。如果设置为 off (默认值),优化器将会忽略隐藏索引(与引入该属性之前的行为相同)。如果设置为 on,隐藏索引仍然不可见,但是优化器在构建执行计划时将会考虑这些索引。
索引的可见性不会影响索引的维护。例如,无论索引是否可见,每次修改表中的数据时都需要对相应索引进行更新,而且唯一索引都会阻止插入重复的列值。
一个没有明确定义主键的表仍然可能存在有效的隐式主键( 表中某些 NOT NULL 字段上创建了 UNIQUE 索引)。在这种情况下,表中第一个这样的索引和显式主键存在相同的约束效果,该索引也不能被设置为不可见。假如存在以下表定义:
CREATE TABLE t2 (
i INT NOT NULL,
j INT NOT NULL,
UNIQUE j_idx (j)
) ENGINE = InnoDB;
定义中没有明确指定主键,但是 NOT NULL 字段 j 上存在一个唯一索引,它实现了和主键相同的数据约束,不能设置为不可见:
mysql> ALTER TABLE t2 ALTER INDEX j_idx INVISIBLE;
ERROR 3522 (HY000): A primary key index cannot be invisible.
如果为该表指定一个显式的主键:
ALTER TABLE t2 ADD PRIMARY KEY (i);
该主键不能设置为不可见。除此之外,字段 j 上的唯一索引不再是一个隐式的主键,因此可以设置为隐藏索引:
mysql> ALTER TABLE t2 ALTER INDEX j_idx INVISIBLE;
Query OK, 0 rows affected (0.03 sec)
隐藏索引应用场景:软删除、灰度发布。
欢迎留言讨论!