pt-duplicate-key-checker
查找 MySQL 表上的重复/冗余索引与重复外键。
语法
bash
pt-duplicate-key-checker [OPTIONS] [DSN]bash
pt-duplicate-key-checker --host host1用法示例
以下示例假定已通过 /etc/my.cnf、~/.my.cnf 或本机 socket 配置好 MySQL 连接;需显式指定连接时加 -h主机 -P端口 -u用户 -p 或 --defaults-file=/path/my.cnf。命令可直接复制,替换其中的库表名即可。
场景:全库扫描冗余索引
拿到一台不熟悉实例的巡检任务,直接全库扫一遍,找出所有重复/冗余索引及其占用空间估算:
bash
pt-duplicate-key-checker场景:只检查某个业务库
只关心某个库,避免把 system / mysql 等系统库一起扫,输出更聚焦:
bash
pt-duplicate-key-checker --databases appdb场景:只检查某几张表
排查某张表是否因加了过多索引而写入变慢时,只扫这几张表:
bash
pt-duplicate-key-checker --tables appdb.orders,appdb.order_items场景:先输出 INVISIBLE 而不是 DROP
生产环境不敢直接删索引时,改用 --invisible 让输出 SQL 把索引设为不可见(不再被优化器使用但写入仍维护),观察一段时间无异常再真正删除;误判时 ALTER INDEX ... VISIBLE 即可秒回:
bash
pt-duplicate-key-checker --invisible --databases appdb场景:只查重复键、跳过外键
只想看冗余索引、不想让重复外键干扰结果时,把检查类型限定为 k(键):
bash
pt-duplicate-key-checker --key-types k --databases appdb功能说明
检查 MySQL 表的 SHOW CREATE TABLE 输出,如果发现与另一索引覆盖相同列(顺序一致), 或恰好覆盖另一索引最左前缀的索引,就打印这些可疑索引。 默认要求索引类型相同:覆盖相同列的 BTREE 索引与 FULLTEXT 索引不算重复(可用选项放开)。
同时检查重复外键:同一张表中覆盖相同列、引用相同父表的外键视为重复。
输出末尾有一个简短摘要,包含重复索引占用空间总量的估算值(字节数), 按索引长度乘以所属表行数计算。
选项
| 选项 | 说明 |
|---|---|
--all-structs | 对比不同结构(BTREE、HASH 等)的索引;默认关闭(BTREE 与 FULLTEXT 覆盖相同列并非真重复) |
--ask-pass | 连接 MySQL 时交互式询问密码 |
--[no]buffer-stdout | 默认开启 STDOUT 缓冲;使用 tee、kubectl logs 等后处理工具想看到实时进度时可关闭 |
-A, --charset | 类型:string。默认字符集(utf8 时设置 binmode/mysql_enable_utf8 并执行 SET NAMES UTF8) |
--[no]clustered | 默认:yes。检测"二级键末尾追加主键列"的冗余:当二级键的后缀是主键最左前缀时视为重复(仅检测主键聚簇的引擎:InnoDB、TokuDB、MyRocks)。聚簇引擎本就把主键列附加到所有二级键的叶子节点,故可视为冗余;但内部节点保留主键列对覆盖索引查询仍有价值,需自行权衡。工具建议缩短冗余的聚簇键;缩短后可能仍与其他键重复,需再次运行检查 |
--config | 类型:Array。读取逗号分隔的配置文件列表;如指定必须放在命令行第一个选项的位置 |
-d, --databases | 类型:hash。只检查这些数据库(逗号分隔) |
-F, --defaults-file | 类型:string。只从给定文件读取 mysql 选项,必须给绝对路径 |
-e, --engines | 类型:hash。只检查存储引擎在此列表中的表 |
--help | 显示帮助并退出 |
-h, --host | 类型:string。要连接的主机 |
--ignore-databases | 类型:Hash。忽略这些数据库 |
--ignore-engines | 类型:Hash。忽略这些存储引擎 |
--ignore-order | 忽略索引列顺序,使 KEY(a,b) 与 KEY(b,a) 互判为重复 |
--ignore-tables | 类型:Hash。忽略这些表(可用库名限定) |
--invisible | 输出的 SQL 把索引设为 INVISIBLE 而不是删除。不可见索引不被优化器考虑但写入时仍维护;发现误判时 ALTER INDEX ... VISIBLE 恢复是 NOOP,而重建索引则是缓慢的 CPU/IO 密集操作 |
--key-types | 类型:string;默认:fk。检查类型:f=外键、k=键、fk=两者 |
-s, --mysql_ssl | 类型:int。创建 SSL MySQL 连接 |
-p, --password | 类型:string。连接密码(含逗号需转义) |
--pid | 类型:string。创建指定的 PID 文件;冲突规则与自动清理见官方文档 |
-P, --port | 类型:int。连接端口 |
--set-vars | 类型:Array。以逗号分隔的 变量=值 列表设置 MySQL 变量;默认 wait_timeout=10000;无法设置时打印警告并继续 |
-S, --socket | 类型:string。连接使用的 socket 文件 |
--[no]sql | 默认:yes。为每个重复键打印 ALTER TABLE ... DROP KEY 语句,便于复制粘贴执行;--no-sql 关闭 |
--[no]summary | 默认:yes。在输出末尾打印索引摘要 |
-t, --tables | 类型:hash。只检查这些表(可用库名限定) |
-u, --user | 类型:string。登录用户(若非当前用户) |
-v, --verbose | 输出所有找到的键/外键,而不只是冗余的 |
--version | 显示版本并退出 |
--[no]version-check | 默认:yes。检查 Percona Toolkit、MySQL 等软件的最新版本与已知问题版本(详见版本检查) |
DSN 选项
| 键 | DSN 部分 | 说明 |
|---|---|---|
A | charset | 默认字符集 |
D | database | 默认数据库 |
F | mysql_read_default_file | 只从给定文件读取默认选项 |
h | host | 要连接的主机 |
p | password | 连接密码(含逗号需转义) |
P | port | 连接端口 |
S | mysql_socket | 连接使用的 socket 文件 |
u | user | 登录用户(若非当前用户) |
s | mysql_ssl | 创建 SSL 连接 |
其他信息
作者:Baron Schwartz 和 Daniel Nichter
通用说明:已知问题的反馈方式、PTDEBUG 调试安全提示、系统要求基线,见 通用说明。
更多细节请阅读 官方文档。