MySQL 支持不可视索引;也就是说,优化器不使用的索引。此功能适用于除主键之外的索引(无论是显式还是隐式)。
索引默认情况下是可见的。要显式控制新索引的可见性,请在 CREATE TABLE
、CREATE INDEX
或 ALTER TABLE
的索引定义中使用 VISIBLE
或 INVISIBLE
关键字。
Press CTRL+C to copyCREATE 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
关键字。
Press CTRL+C to copyALTER TABLE t1 ALTER INDEX i_idx INVISIBLE; ALTER TABLE t1 ALTER INDEX i_idx VISIBLE;
有关索引是否可见的信息可以在 Information Schema STATISTICS
表或 SHOW INDEX
输出中找到。例如
Press CTRL+C to copymysql> 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 | +------------+------------+
不可视索引使得能够测试删除索引对查询性能的影响,而无需进行破坏性更改,如果索引被证明是必需的,则必须撤消该更改。删除和重新添加索引对于大型表来说可能很昂贵,而将其设为不可视和可见是快速且就地的操作。
如果设为不可视的索引实际上是需要的或被优化器使用,则有几种方法可以注意到其缺席对该表查询的影响。
包含引用不可视索引的索引提示的查询将出现错误。
Performance Schema 数据显示受影响查询的工作负载增加。
查询具有不同的
EXPLAIN
执行计划。查询出现在以前没有出现的慢查询日志中。
系统变量 optimizer_switch
的 use_invisible_indexes
标志控制优化器是否使用不可视索引来构建查询执行计划。如果该标志为 off
(默认值),优化器将忽略不可视索引(与引入该标志之前相同)。如果该标志为 on
,不可视索引将保持不可视,但优化器将在构建执行计划时考虑它们。
使用 SET_VAR
优化器提示来临时更新 optimizer_switch
的值,您可以仅在单个查询期间启用不可视索引,如下所示。
Press CTRL+C to copymysql> EXPLAIN SELECT /*+ SET_VAR(optimizer_switch = 'use_invisible_indexes=on') */ > i, j FROM t1 WHERE j >= 50\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: t1 partitions: NULL type: range possible_keys: j_idx key: j_idx key_len: 5 ref: NULL rows: 2 filtered: 100.00 Extra: Using index condition mysql> EXPLAIN SELECT i, j FROM t1 WHERE j >= 50\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: t1 partitions: NULL type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 5 filtered: 33.33 Extra: Using where
索引可见性不会影响索引维护。例如,索引会根据表行更改继续更新,并且唯一索引会阻止将重复项插入列,无论索引是可见还是不可见。
没有显式主键的表如果在 NOT NULL
列上具有任何 UNIQUE
索引,则可能仍然具有有效的隐式主键。在这种情况下,第一个这样的索引对表行施加与显式主键相同的约束,并且该索引不能设为不可见。考虑以下表定义。
Press CTRL+C to copyCREATE TABLE t2 ( i INT NOT NULL, j INT NOT NULL, UNIQUE j_idx (j) ) ENGINE = InnoDB;
该定义不包含显式主键,但 NOT NULL
列 j
上的索引对行施加与主键相同的约束,并且不能设为不可见。
Press CTRL+C to copymysql> ALTER TABLE t2 ALTER INDEX j_idx INVISIBLE; ERROR 3522 (HY000): A primary key index cannot be invisible.
现在假设向表中添加了显式主键。
Press CTRL+C to copyALTER TABLE t2 ADD PRIMARY KEY (i);
显式主键不能设为不可见。此外,j
上的唯一索引不再充当隐式主键,因此可以设为不可见。
Press CTRL+C to copymysql> ALTER TABLE t2 ALTER INDEX j_idx INVISIBLE; Query OK, 0 rows affected (0.03 sec)