php SQL慢查询、未加索引

一、成因分析

  1. 未加索引:WHERE、JOIN、ORDER BY、GROUP BY等字段未建索引,导致全表扫描
  2. 索引未命中:SQL写法不当,索引失效
  3. 大表无分区/分表:数据量大,单表查询慢
  4. SQL语句低效:子查询、嵌套、函数、模糊匹配等
  5. 统计/聚合操作无优化:COUNT、SUM等全表聚合
  6. 数据类型不合理:字段类型过大、未规范化

二、排查与定位

1. 开启慢查询日志

MySQL配置:

SET GLOBAL slow_query_log = 1;
SET GLOBAL slow_query_log_file = '/var/log/mysql-slow.log';
SET GLOBAL long_query_time = 1;  -- 超过1秒的SQL记录为慢查询

2. 分析慢查询日志

  • mysqldumpslowpt-query-digest等工具分析慢SQL
  • 关注执行频率高、耗时长的SQL

3. EXPLAIN分析执行计划

EXPLAIN SELECT * FROM users WHERE email = 'test@example.com';
  • 关注type(最好为constrefrange),key(用到索引),rows(扫描行数)

三、优化思路与技巧

1. 为查询条件加索引

  • WHERE、JOIN、ORDER BY、GROUP BY等常用字段加索引
  • 唯一性高的字段优先加索引(如user_id、email、order_no)

示例:

ALTER TABLE users ADD INDEX idx_email (email);
ALTER TABLE orders ADD INDEX idx_userid_status (user_id, status);

2. 联合索引与索引顺序

  • 多条件查询用联合索引,顺序要与SQL条件一致
  • 最左前缀原则:WHERE user_id=1 AND status=1,索引(user_id, status)有效

3. 避免索引失效的写法

  • 不要在索引字段上用函数、运算、隐式类型转换
  • LIKE '%xxx’无法用索引,LIKE 'xxx%'可用
  • OR连接的字段都要有索引

示例:

-- 索引失效
SELECT * FROM users WHERE LEFT(email, 3) = 'abc';

-- 索引有效
SELECT * FROM users WHERE email LIKE 'abc%';

4. 分页优化

  • 大数据量分页用索引覆盖或延迟关联,避免OFFSET大时全表扫描

示例:

-- 慢:OFFSET越大越慢
SELECT * FROM orders ORDER BY id LIMIT 100000, 20;

-- 快:用索引覆盖
SELECT * FROM orders WHERE id > 100000 ORDER BY id LIMIT 20;

5. 分区/分表

  • 大表按时间、用户ID等分区/分表,减少单表数据量

6. SQL语句优化

  • 避免SELECT *,只查需要的字段
  • 用JOIN代替子查询
  • 聚合操作加索引或用中间表

7. 定期维护与监控

  • 定期ANALYZE TABLEOPTIMIZE TABLE,保持索引和统计信息新鲜
  • 监控慢SQL、索引命中率

四、实际操作流程举例

  1. 开启慢查询日志,收集慢SQL
  2. 用EXPLAIN分析慢SQL执行计划
  3. 为WHERE/JOIN/ORDER BY等字段加索引
  4. 优化SQL写法,避免索引失效
  5. 大表分区/分表,分页用索引覆盖
  6. 定期维护和监控,持续优化

五、PHP开发中的实践

1. 查询前用EXPLAIN分析SQL

$stmt = $pdo->query("EXPLAIN SELECT * FROM users WHERE email = 'test@example.com'");
print_r($stmt->fetchAll());

2. 用参数化查询防SQL注入

$stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?");
$stmt->execute([$email]);

六、总结

  • SQL慢查询、未加索引是数据库性能杀手
  • 优化核心是加索引、写好SQL、分区分表、定期维护
  • 先定位慢点,再针对性优化,持续监控

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

贵哥的编程之路(热爱分享 为后来者)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值