ALTER TABLE ALTER INDEX INVISIBLE是唯一合法切换方式,仅改元数据、毫秒完成但受MDL锁影响;新建索引时加INVISIBLE更稳妥;主键、隐式主键、FULLTEXT等不支持;需查INFORMATION_SCHEMA.STATISTICS.IS_VISIBLE='NO'并对比EXPLAIN key变化验证生效。

ALTER TABLE ALTER INDEX INVISIBLE 是唯一安全切换方式
想验证删索引会不会出事,不能直接 DROP,也不能用 MODIFY INDEX 或 SET INVISIBLE——这些语法全报错。唯一合法路径是:ALTER TABLE table_name ALTER INDEX index_name INVISIBLE;。它只改元数据,不重建 B+ 树,毫秒完成,但会短暂持有元数据锁(MDL),长事务未提交时 DDL 会被阻塞。
新建索引时加 INVISIBLE 更稳妥,比如:CREATE INDEX idx_status ON orders(status) INVISIBLE;,完全避开锁竞争风险。注意:主键、第一个 UNIQUE NOT NULL 索引、FULLTEXT、SPATIAL 都不支持设为不可见,强行执行会触发 ERROR 3522 或 ERROR 1214。
EXPLAIN 不显示不可见索引是设计行为,不是 bug
EXPLAIN 里压根不会把不可见索引纳入候选集,所以 key 字段为空、或退化为 type: ALL,才是它真正被忽略的信号。别指望 SHOW INDEX FROM table_name 的 Comment 字段——它恒为 NULL,毫无参考价值。
验证是否生效,必须做两件事:
- 查系统表:
SELECT IS_VISIBLE FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_NAME = 'orders' AND INDEX_NAME = 'idx_status';,返回字符串'NO'才算成功 - 跑真实查询:
EXPLAIN SELECT * FROM orders WHERE status = 'shipped';,对比切换前后key和rows变化
如果代码里写了 FORCE INDEX (idx_status),EXPLAIN 会直接报 ERROR 1176: Key 'idx_status' doesn't exist——这不是索引没了,是优化器在常规路径下已“注销”它。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
观察指标不能只盯一条 EXPLAIN,得看真实负载下的三类信号
切为不可见后,至少观察 24 小时,重点不是 COUNT_STAR = 0(performance_schema.table_io_waits_summary_by_index_usage),而是业务是否真扛得住退化:
- 慢查询日志中,原本走该索引的语句
Query_time是否明显升高,Rows_examined是否暴涨 -
Handler_read_next或Handler_read_rnd_next是否突增(说明退化为全表扫描或文件排序) - 应用层是否有超时告警,尤其是低频但关键的定时任务(比如凌晨报表),它们可能一天只跑一次,但删了就崩
写入侧没变化:innodb_rows_inserted、innodb_buffer_pool_reads 不会因隐藏而降低——不可见索引仍要维护唯一性、占用磁盘、产生写入开销。
灰度测试前必须扫清三个绕过可见性的失效点
隐藏索引在生产环境容易“形同虚设”,因为:
- 有人提前打开了
use_invisible_indexes=on(查SELECT @@optimizer_switch LIKE '%use_invisible_indexes=on%'),导致优化器照常选用 - 应用代码或 ORM 配置里硬写了
FORCE INDEX或USE INDEX,它们不检查可见性,直接干预选索引逻辑 - 备份还原后行为突变:
mysqldump默认不导出INVISIBLE关键字,还原后索引自动变回VISIBLE
最危险的是 FORCE INDEX —— 它让测试完全失真,但又极难被发现,必须全量扫描 SQL、存储过程、ORM 配置和中间件 SQL 拦截逻辑。










