不能,pt-duplicate-key-checker基于information_schema.statistics自动对齐列序、归一化前缀长度并比对索引类型,标记“可安全删除”或“需人工确认”,而手动查information_schema仅匹配列名与顺序,易漏sub_part或index_type差异。

pt-duplicate-key-checker 能直接替代手动查 information_schema 吗
不能,它补的是人工判断短板,不是元数据查询缺口。工具输出基于 information_schema.statistics,但会自动做列顺序对齐、前缀长度归一化、索引类型比对(比如 BTREE vs HASH),并标记「可安全删除」「需人工确认」两类结果。而纯 SQL 查询(如 GROUP_CONCAT(column_name ORDER BY seq_in_index))只管列名和顺序一致,漏掉 sub_part 不同或 index_type 不同的“伪重复”。
执行 pt-duplicate-key-checker 时常见报错和绕过方式
最常遇到的是权限不足或连接超时,不是工具本身问题:
-
Access denied for user:必须授予SELECT权限给information_schema和目标库,且需PROCESS权限(用于读取线程状态) -
Lost connection to MySQL server:大库默认超时,加参数--set-vars wait_timeout=28800 -
Can't connect to local MySQL server:Mac 上用 Homebrew 安装后,可能默认连/tmp/mysql.sock,但你的 MySQL 实际用的是/var/run/mysqld/mysqld.sock,显式指定--socket=/var/run/mysqld/mysqld.sock - 不支持 MySQL 8.0+ 的 caching_sha2_password 插件认证?加
--defaults-file指向含明文密码的配置文件,或临时改用户认证方式:ALTER USER 'u'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd';
输出里标 “duplicate” 和 “redundant” 的区别在哪
这是最关键的判断依据,别凭感觉删:
-
duplicate:同一张表上,完全相同的列组合 + 相同顺序 + 相同索引类型 + 相同前缀长度(sub_part)→ 可无脑留一个,删其余 -
redundant:比如已有INDEX(a,b,c),又建了INDEX(a,b)或INDEX(a)→ 前者是前缀覆盖,后者是前缀的前缀;但INDEX(a,c)不算冗余,因为跳过了b,无法被覆盖 - 工具还会标注是否被
UNIQUE或PRIMARY KEY隐式占用,比如你看到redundant却带[unique]标签,说明这索引实际承担唯一性约束,删了INSERT IGNORE就失效
删之前必须验证的三个现场行为
工具只告诉你“长得像”,不告诉你“有没有真在跑”:
- 查
performance_schema.table_io_waits_summary_by_index_usage(MySQL 8.0+):确认COUNT_STAR = 0且COUNT_READ = 0,否则说明该索引还在被某些慢查询或后台任务用着 - 对核心业务 SQL 手动
EXPLAIN:比如有个ORDER BY created_at DESC LIMIT 20,即使没WHERE,也可能依赖INDEX(status, created_at)做索引排序;删了就触发Using filesort - 检查是否有触发器、外键或分区表逻辑依赖该索引:特别是
ALTER TABLE ... REORGANIZE PARTITION过程中手动加的局部索引,DROP INDEX会全局生效,可能破坏分区一致性
真正容易被忽略的是:InnoDB 二级索引叶子节点存主键值,所以 INDEX(a) 和 INDEX(a,b) 在回表代价上差异极大——前者查出主键再回聚簇索引取 b,后者直接拿到 b。删 INDEX(a) 看似安全,但若某条 SQL 只要 a 不要 b,反而多了一次回表。











