文档首页
MySQL 9.0 参考手册
相关文档 下载本手册
PDF (美国信纸) - 40.0Mb
PDF (A4) - 40.1Mb
手册页 (TGZ) - 258.2Kb
手册页 (Zip) - 365.3Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 9.0 参考手册  /  ...  /  不可見索引

10.3.12 不可见索引

MySQL 支持不可见索引;也就是说,优化器不使用的索引。此功能适用于除主键之外的索引(显式或隐式)。

索引默认情况下是可见的。要显式控制新索引的可见性,请在为 CREATE TABLECREATE INDEXALTER TABLE 定义索引时使用 VISIBLEINVISIBLE 关键字。

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 操作中使用 VISIBLEINVISIBLE 关键字。

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         |
+------------+------------+

不可见索引使您可以测试删除索引对查询性能的影响,而无需进行破坏性更改,如果事实证明该索引是必需的,则必须撤消该更改。删除和重新添加索引对于大型表来说可能很昂贵,而使其不可见和可见则是快速的在位操作。

如果不可见的索引实际上需要或被优化器使用,则有几种方法可以注意到其缺席对该表查询的影响

  • 对包含引用不可见索引的索引提示的查询会发生错误。

  • Performance Schema 数据显示受影响查询的工作负载增加。

  • 查询具有不同的 EXPLAIN 执行计划。

  • 查询出现在慢查询日志中,而以前没有出现在那里。

use_invisible_indexesoptimizer_switch 系统变量的标志,用于控制优化器是否使用不可见索引来构建查询执行计划。如果该标志为 off(默认值),优化器会忽略不可见索引(与引入该标志之前行为相同)。如果该标志为 on,不可见索引仍然不可见,但优化器会在构建执行计划时考虑它们。

使用 SET_VAR 优化器提示临时更新 optimizer_switch 的值,您可以只对单个查询启用不可见索引,例如

mysql> 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 索引,则可能仍具有有效的隐式主键。在这种情况下,第一个这样的索引对表行施加与显式主键相同的约束,并且该索引不能变为不可见。考虑以下表定义

CREATE TABLE t2 (
  i INT NOT NULL,
  j INT NOT NULL,
  UNIQUE j_idx (j)
) ENGINE = InnoDB;

该定义不包含显式主键,但 NOT NULLj 上的索引对行施加与主键相同的约束,并且不能变为不可见

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)