慢查询是数据库优化的首要切入点,因其导致80%以上性能问题;需开启慢查询日志并用pt-query-digest分析,而非仅依赖EXPLAIN。

为什么慢查询是数据库优化的首要切入点
数据库性能问题80%以上源于SQL执行效率低,而不是服务器配置或PHP代码本身。面试官常通过“你如何定位慢查询”考察实际经验。核心方法是开启MySQL慢查询日志(slow_query_log=ON),设置合理阈值(如long_query_time=1),再配合pt-query-digest分析日志,快速识别TOP 10耗时SQL。不建议只依赖EXPLAIN看单条语句——真实瓶颈往往藏在高频但未加索引的简单查询里,比如SELECT * FROM user WHERE status = 1在百万级表中没走索引,比复杂JOIN更伤性能。
索引不是越多越好:三个必须掌握的设计原则
面试常问“给user表的name和email字段都建索引是否合理”,答案是否定的。关键看查询模式和数据分布:
-
最左前缀原则要落地:联合索引
(city, age, status)能加速WHERE city='北京' AND age>25,但对WHERE age>25无效;如果常查status单独条件,需另建单列索引 -
区分度优先于字段长度:对性别字段(只有男/女)建索引几乎无用,而对订单号(唯一且长)建索引收益极高;可用
SELECT COUNT(DISTINCT column)/COUNT(*) FROM table估算区分度 -
写多读少的字段慎建索引:如记录操作日志的
updated_at,频繁UPDATE会导致索引页分裂,反而拖慢整体写入
PHP层能做的三件关键小事
很多人忽略应用层对数据库的压力传导。以下操作成本低、见效快:
-
禁用PDO的预处理模拟:MySQL原生预处理(
PDO::ATTR_EMULATE_PREPARES = false)可避免PHP层拼接SQL,减少SQL注入风险的同时,让MySQL真正复用执行计划 -
批量操作代替循环单条:用
INSERT INTO t VALUES (),(),()一次插入100行,比100次$pdo->exec("INSERT ...")快5-10倍,网络往返和事务开销大幅降低 -
结果集及时释放:处理完大数据量查询后调用
$stmt->closeCursor(),避免PDO内部缓存占用内存,尤其在CLI脚本中易引发OOM
分库分表不是银弹:先看这四个信号
面试官可能追问“用户表超千万行是否该分表”。正确思路是先排查基础优化是否到位,再观察具体指标:
立即学习“PHP免费学习笔记(深入)”;
- 单表主键自增ID已接近INT上限(约21亿),继续插入会报错,此时必须拆分
- 慢查询集中在某几个热点用户(如明星账号动态),可用哈希分表隔离压力,而非全量水平拆分
- ALTER TABLE锁表时间超过业务容忍阈值(如>30秒),说明单表维护成本过高
- 从库延迟持续>60秒,且确认非网络或硬件问题,大概率是单主写入能力已达瓶颈
过早分库分表会显著增加PHP代码复杂度(路由逻辑、跨库JOIN、分布式事务),多数中小项目用读写分离+合适的索引就能扛住日活百万级流量。











