同一个索引,只切换INVISIBLE和VISIBLE,看优化器是不是真的完全无视了它,以及不删索引也能做到的'软下线'为什么比直接DROP更安全。
amount列上已经有一个真实索引idx_amount,用ALTER TABLE切换它的可见性,索引本身不删除也不重建。
代码ALTER TABLE orders ALTER INDEX idx_amount INVISIBLE; -- 索引真实还在,只是优化器默认不再考虑用它 ALTER TABLE orders ALTER INDEX idx_amount VISIBLE; -- 改回可见,索引不需要重建
索引可见:
-> Index range scan on orders using idx_amount over (490.00 <= amount <= 495.00) (cost=237 rows=526)
索引不可见:
-> Filter: (orders.amount between 490 and 495) (cost=5124 rows=5488)
-> Table scan on orders (cost=5124 rows=49396) ← 完全无视idx_amount,退化成全表扫描索引标记成INVISIBLE之后,优化器在选执行计划的时候真实把这个索引当成不存在——EXPLAIN里连提都不提idx_amount,直接走了全表扫描。这个操作不涉及删除或重建索引,索引数据在磁盘上原封不动,后台的INSERT/UPDATE/DELETE依然会真实继续维护它,只是查询优化阶段真实不再把它纳入候选。
索引可见,走idx_amount: 1332 微秒 (约1.33毫秒) 索引不可见,走全表扫描: 18504 微秒 (约18.5毫秒) ← 慢了约13.9倍 SET SESSION optimizer_switch='use_invisible_indexes=on'; -- 索引依然标记为INVISIBLE,但这个开关打开后: -> Index range scan on orders using idx_amount ... ← 又真实用回索引了
每一步都是本文上面用EXPLAIN和真实计时跑出来的原始结果。
ALTER TABLE ... ALTER INDEX ... INVISIBLE/VISIBLEoptimizer_switch='use_invisible_indexes=on':不改索引状态也能强制启用