ThinkPHP数据库优化技巧有哪些
导读:ThinkPHP数据库优化技巧清单 一 查询与索引优化 只查需要的字段,避免 **SELECT ***,减少网络与内存开销。示例:field('id,name,email' 。 为高频出现在 WHERE、JOIN、ORDER BY、GRO...
ThinkPHP数据库优化技巧清单
一 查询与索引优化
- 只查需要的字段,避免 **SELECT ***,减少网络与内存开销。示例:
field('id,name,email')。 - 为高频出现在 WHERE、JOIN、ORDER BY、GROUP BY 的字段建立索引;多条件组合使用联合索引并遵循最左前缀原则;外键如 user_id 建议加索引。
- 避免索引失效:不要在 WHERE 中对字段做函数或计算(如
WHERE YEAR(create_time)=2024),尽量改写为范围或等值条件。 - 优化分页:列表页优先基于主键/索引列做游标分页(如
where('id','> ',$lastId)-> limit(N)),避免大偏移的OFFSET。 - 复杂查询使用 EXPLAIN 检查执行计划,关注
type(尽量避免 ALL)、key、rows、Extra中的 Using filesort/Using temporary。 - 必要时使用原生SQL或查询构造器的子查询/联表,比层层循环更高效。
- 开启并分析 SQL 日志,定位慢查询与高频 SQL。
二 关联与缓存策略
- 解决 N+1 查询:在列表场景用 with 预加载一次性取出关联数据,避免在模板或循环中逐条查询。
- 合理使用查询缓存与数据缓存(如 Redis/Memcached):对读多写少、结果较稳定的接口或字典表设置合理 TTL,并在数据变更时主动失效。
- 区分页面缓存与数据缓存的适用场景,避免缓存穿透/雪崩(如设置随机过期、降级兜底)。
三 架构与连接管理
- 读写分离:在配置中设置主库写、从库读,将报表、搜索等读压力分摊到从库。
- 分库分表:对大表按业务键拆分,配合中间件或自研路由,降低单库单表压力。
- 选择合适的缓存与存储:将会话、热点数据、计数等放入 Redis,对日志/非结构化数据考虑 MongoDB。
- 连接管理:避免连接泄露,合理配置连接池与超时;应用侧复用连接、及时释放。
四 监控与数据库配置
- 慢查询治理:开启 slow_query_log 与 long_query_time,用
EXPLAIN与性能工具定位瓶颈。 - 服务器参数:适当调大 innodb_buffer_pool_size,提升缓冲命中率;合理设置 max_connections 与超时参数。
- 运行时可观测性:在 config/database.php 记录 SQL 日志,或用 Db::listen 监听 SQL 与耗时,配合 Xdebug/Blackfire 做全链路分析。
- 生产环境关闭调试模式,减少额外开销。
五 可直接复用的优化示例
- 列表页预加载 + 游标分页(避免 N+1 与大偏移)
$list = UserModel::with(['profile', 'orders'])
->
where('status', 1)
->
where('id', '>
', $lastId)
->
order('id', 'asc')
->
limit(20)
->
select();
- 查询缓存 + 索引提示(稳定字典/配置)
$config = cache('config_dict');
if (!$config) {
$config = ConfigModel::where('status', 1)
->
field('k,v')
->
useIndex('idx_status') // 视库表支持情况使用
->
select()
->
column('v', 'k');
cache('config_dict', $config, 3600);
// 1小时
}
- 原生 SQL + EXPLAIN 定位慢查询
// 开发/预发环境先分析
$sql = "SELECT u.id,u.name,o.total FROM user u
JOIN `order` o ON o.user_id = u.id
WHERE u.status = ? AND o.create_time >
= ?
ORDER BY o.create_time DESC LIMIT 50";
Db::listen(function($sql, $runtime) {
// 记录或上报慢 SQL
if ($runtime >
0.2) {
// 告警/写入慢查询日志
}
}
);
$rows = Db::query($sql, [1, '2025-01-01']);
// 用 EXPLAIN 检查是否走索引、是否出现 Using filesort/Using temporary
- 读写分离配置(示例)
// config/database.php
'connections' =>
[
'mysql' =>
[
'type' =>
'mysql',
'hostname' =>
'write.db.local',
'database' =>
'app',
'username' =>
'write',
'password' =>
'***',
'deploy' =>
1, // 启用分布式
'rw_separate' =>
true, // 开启读写分离
'master_num' =>
1,
'slave_no' =>
[], // 读库序号,可配多个
],
]
声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!
若转载请注明出处: ThinkPHP数据库优化技巧有哪些
本文地址: https://pptw.com/jishu/757412.html
