ThinkPHP6 查询慢如何开启 SQL 日志分析优化索引

文章导读
面对 ThinkPHP6 查询慢的问题,最稳妥的做法是在开发环境开启应用调试日志定位 SQL,而在生产环境优先依赖数据库自身的慢查询日志,避免应用层记录带来的额外开销。
📋 目录
  1. ThinkPHP6 配置 SQL 日志
  2. MySQL 慢查询日志配置
  3. 索引优化实操
  4. 验证优化效果
  5. 常见风险与坑
  6. 参考来源
A A

面对 ThinkPHP6 查询慢的问题,最稳妥的做法是在开发环境开启应用调试日志定位 SQL,而在生产环境优先依赖数据库自身的慢查询日志,避免应用层记录带来的额外开销。

先说结论:不要直接在生产环境开启 ThinkPHP 的全量 SQL 日志,应先用数据库慢查询日志锁定问题语句,再结合 EXPLAIN 分析索引。

  • 先定位:确认慢查询是偶发还是常态,区分是应用层逻辑还是数据库层瓶颈。
  • 先做:开启 MySQL 慢查询日志或临时开启 TP 调试模式抓取特定 SQL。
  • 再验证:通过 EXPLAIN 分析执行计划,添加索引后对比执行时间。

ThinkPHP6 配置 SQL 日志

ThinkPHP6 的 SQL 日志机制不仅依赖全局调试开关,还需确保数据库连接配置启用了调试。仅修改 `.env` 中的 `APP_DEBUG` 可能不足以记录详细 SQL 执行信息。

1. 修改 .env 文件(开发环境)

APP_DEBUG=true

2. 配置 database.php(关键步骤)

检查 `config/database.php` 文件,确保对应连接配置中 `debug` 参数为 `true`。这是框架记录 SQL 日志的直接开关。

return [
    // 默认数据库连接配置
    'default' => 'mysql',
    'connections' => [
        'mysql' => [
            // 其他配置...
            'debug' => true, // 开启 SQL 日志记录
        ],
    ],
];

配置生效后,日志文件通常位于 `runtime/log` 目录下,可通过 `tail -f` 实时查看。

MySQL 慢查询日志配置

生产环境建议通过数据库层面记录慢 SQL。根据数据库部署方式不同,配置方法有所区别。

1. 自建数据库(修改 my.cnf)

ThinkPHP6 查询慢如何开启 SQL 日志分析优化索引

编辑 MySQL 配置文件(通常位于 `/etc/my.cnf` 或 `/etc/mysql/my.cnf`),在 `[mysqld]` 段落下添加以下配置以实现永久生效:

[mysqld]
slow_query_log = 1
slow_query_log_file = /var/log/mysql/mysql-slow.log
long_query_time = 2
log_queries_not_using_indexes = 1

修改后需重启 MySQL 服务:`systemctl restart mysqld`。

2. 云数据库(RDS/Aurora 等)

云数据库实例通常禁止执行 `SET GLOBAL` 命令。需在云厂商控制台找到“参数组”或“实例配置”,修改 `slow_query_log` 和 `long_query_time` 参数后重启实例或应用参数。

索引优化实操

从慢查询日志中提取执行时间超过阈值的 SQL 语句,使用 `EXPLAIN` 分析执行计划。重点关注 `type` 是否为 `ALL` 或 `index`,以及 `key` 是否为 NULL。

EXPLAIN SELECT * FROM orders WHERE user_id = 1001;

若发现缺失索引,根据查询条件字段添加索引。以下是添加普通索引和联合索引的 SQL 示例:

-- 添加单列索引
ALTER TABLE orders ADD INDEX idx_user_id (user_id);

-- 添加联合索引(注意最左前缀原则)
ALTER TABLE orders ADD INDEX idx_user_status (user_id, status);

注意:对百万级以上数据量的表执行 `ALTER TABLE` 可能会锁表,建议在业务低峰期操作,或使用在线 DDL 工具(如 pt-online-schema-change)。

验证优化效果

优化完成后,通过以下方式确认效果:

  • 日志对比:观察数据库慢查询日志中,该条 SQL 是否不再出现或执行时间显著降低。
  • 执行计划:再次使用 `EXPLAIN` 命令,确认 `key` 字段已显示为新添加的索引名,且 `rows` 扫描行数减少。
  • 应用监控:在 ThinkPHP 调试模式下,查看页面底部或日志中该次查询的 `RunTime` 数值变化。

常见风险与坑

  • 生产环境误开调试:切勿将 `APP_DEBUG=true` 或数据库 `debug => true` 部署到生产环境,这不仅影响性能,还可能泄露数据库结构等敏感信息。排查完毕后务必关闭。
  • 云数据库权限限制:在云数据库上执行 `SET GLOBAL slow_query_log = 'ON'` 通常会报错(ERROR 1227),请改用控制台参数组配置。
  • 日志磁盘爆满:开启慢查询日志后,若不限制日志文件大小或定期清理,可能占满磁盘空间。建议配置日志轮转(log_rotate)。
  • 索引失效场景:即使加了索引,如果查询条件使用了函数、模糊查询 `%` 在前或类型隐式转换,索引依然可能失效,需结合 `EXPLAIN` 具体判断。

参考来源

  • ThinkPHP 6.0 官方文档,数据库配置与调试说明,https://doc.thinkphp.cn/
  • MySQL 官方文档,Slow Query Log 配置说明,https://dev.mysql.com/doc/