Skip to content

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 部分说明
Acharset默认字符集
Ddatabase默认数据库
Fmysql_read_default_file只从给定文件读取默认选项
hhost要连接的主机
ppassword连接密码(含逗号需转义)
Pport连接端口
Smysql_socket连接使用的 socket 文件
uuser登录用户(若非当前用户)
smysql_ssl创建 SSL 连接

其他信息

  • 作者:Baron Schwartz 和 Daniel Nichter

  • 通用说明:已知问题的反馈方式、PTDEBUG 调试安全提示、系统要求基线,见 通用说明

更多细节请阅读 官方文档

Percona Toolkit 中文文档 · 社区维护的第三方学习站