mysql 8.0 隐藏索引仅支持 sql 命令 alter table ... alter index ... invisible/visible,gui 工具不支持;primary key 不可隐藏;生效需 explain 验证,默认不使用隐藏索引,且写入仍维护该索引。

ALTER TABLE ALTER INDEX INVISIBLE 是唯一生效方式
MySQL 8.0 的隐藏索引不支持 GUI 工具点选切换,Workbench、DBeaver、Navicat 等所有可视化界面都不提供「设为隐藏」按钮。右键索引 → 修改 → 执行后毫无变化,不是 bug,是功能根本没实现。
真正能生效的只有 SQL:
-
ALTER TABLE orders ALTER INDEX idx_user_id INVISIBLE(设为隐藏) -
ALTER TABLE orders ALTER INDEX idx_user_id VISIBLE(恢复可见) - 新建时直接加:
CREATE INDEX idx_email ON users(email) INVISIBLE
操作是元数据级变更,毫秒完成,不锁表、不重建 B+ 树。但注意:PRIMARY KEY 和隐式主键(如第一个 UNIQUE NOT NULL 索引)禁止设为 INVISIBLE,否则报错 ERROR 3522 (HY000): A primary key index cannot be invisible。
验证隐藏是否真生效,不能只看 SHOW INDEX
SHOW INDEX FROM orders\G 输出里的 Visible: NO 是可靠信号,但 Comment 字段恒为 NULL,别信它;information_schema.statistics 中的 IS_VISIBLE 字段值是字符串 'YES' 或 'NO',不是布尔值。
更关键的是执行计划验证:
- 执行
EXPLAIN SELECT * FROM orders WHERE user_id = 123 - 如果之前走
idx_user_id,现在变成type: ALL或换用其他索引,才说明隐藏成功 - 刚执行完
ALTER就查information_schema可能有毫秒级延迟,建议优先以EXPLAIN结果为准
若仍走该索引,大概率是会话或全局开启了 use_invisible_indexes=on,查 SELECT @@optimizer_switch LIKE '%use_invisible_indexes=on%' 确认。
EXPLAIN 默认不走隐藏索引,必须手动启用才能对比
默认情况下,EXPLAIN 完全无视隐藏索引——哪怕你写 FORCE INDEX(idx_user_id),也会直接报错 ERROR 1176 (HY000): Key 'idx_user_id' doesn't exist in table 'orders'。
想做真实对比,必须显式启用:
- 会话级(推荐):
SET SESSION optimizer_switch = 'use_invisible_indexes=on';,然后跑EXPLAIN - SQL 级(更安全):
SELECT /*+ SET_VAR(optimizer_switch = 'use_invisible_indexes=on') */ * FROM orders WHERE user_id = 123;再EXPLAIN
两次 EXPLAIN 必须在相同 session 下做,且确保没被其他 optimizer_switch 设置干扰(比如 use_index_extensions=off 可能掩盖效果)。
线上灰度观察不能只盯单条 EXPLAIN
隐藏索引对优化器“不可见”,但 INSERT/UPDATE/DELETE 仍照常维护它:磁盘空间不释放、写入开销不降低、UNIQUE 约束依然校验。所以它不是性能开关,而是验证开关。
真实影响要看业务负载:
- 慢查询日志里原本不慢的 SQL 是否
Query_time明显升高 -
performance_schema.table_io_waits_summary_by_index_usage中对应索引的COUNT_STAR是否归零 -
sys.schema_unused_indexes视图是否持续显示该索引未被使用
观察周期建议 ≥ 24 小时,覆盖完整业务波峰波谷;期间若异常,ALTER TABLE ... VISIBLE 秒级回滚。最容易漏掉的点是:以为设成 INVISIBLE 就等于“关掉了索引”,其实写入负担一毛不少,也完全不影响主从同步延迟。











