已采纳
回答正文
回复
讨论正文
该问题的正文与回答。
做了 8 年 DBA,慢查询治理和索引管理是日常。最近接手一套 MySQL 8.0.34(InnoDB,16C64G,buffer_pool 32G)的核心业务库,其中一张 t_settlement_detail 表约 4500 万行、单行平均 280B(含一个 JSON 列),上面挂了 6 个二级索引。
业务方说"其中两个索引是三年前某个报表需求建的,那个报表已经下线了"。如果确认废弃,删掉后写入路径少维护 2 棵 B+Tree,按 InnoDB 每个二级索引每行都要更新来算,写入放大至少降 1/3,对这张表日均 80 万次 UPDATE 的场景意义不小。
performance_schema 的 table_io_waits_summary_by_index_usage 表我们没开(生产环境当年为了省内存没启用),sys.schema_unused_indexes 视图依赖它,所以拿不到"该索引自实例启动以来被访问次数为 0"的证据。slow_query_log 只记录 SQL 文本和耗时,不记录"实际用了哪个索引"。即使把 log_queries_not_using_indexes 打开,也只能看到"没走索引"的 SQL,不能反过来证明"某索引被用了"。performance_schema,也只能采集"从现在开始"的数据,无法回溯过去 11 个月的使用情况。SHOW INDEX FROM t_settlement_detail 看索引创建时间,确认那 2 个索引确实是三年前创建的(CREATE INDEX 语句在 binlog 里能查到)。idx_report_date 和 idx_biz_type_status),近 12 个月的 commit 里没有新增引用,但不能排除定时任务或运维临时查询还在用。information_schema.statistics 确认这两个索引的 CARDINALITY,发现 idx_biz_type_status 的基数只有 147(对 4500 万行来说选择性极低),优化器大概率不会选它——但"大概率不选"不等于"没人显式 FORCE INDEX"。SET GLOBAL performance_schema=ON 在线开启(MySQL 8.0 支持动态开关),但担心开启瞬间 table_io_waits_summary_by_index_usage 的计数器从 0 开始,而我们要证明的是"过去 11 个月没人用过",这个窗口覆盖不了。我需要的不是一个"建议打开 performance_schema"的泛泛之谈,而是:
performance_schema 没开 / 刚开 / 只能采集未来数据的前提下,怎么把"该索引可以安全删除"的置信度推到可接受水平?(比如:开 P_S 采集 N 天 → 同时 grep 应用 + 定时任务 + binlog → 灰度期只禁不删 → 正式删,每一步的具体判据是什么?)CREATE INDEX 的 Online DDL 大概要多久、对在线写入的影响多大?有没有比"删了再建"更安全的过渡方案(比如先 ALTER INDEX INVISIBLE 不可见化)?慢查询治理三件套里提到"先定位再判断最后加索引"的顺序(id=19),我的场景反过来了:不是"要不要加"而是"要不要删",判断依据的获取方式完全不同。