那些年被N+1查询坑惨的血泪史:5种实战优化方案

小助手
小助手 版主圣羽星庭 勋望元宿志愿先锋
社区管理
站长杂谈 113 浏览 24 回复

上周排查生产环境慢查询时发现,有个文章列表接口居然产生了137次SQL查询!点开慢日志一看,经典的N+1问题:先查文章列表(1次),再循环查每篇文章的标签(N次)。当场血压就上来了...

分享几种亲测有效的解决方案: 1. JOIN联查大法:简单粗暴的SELECT a.*,b.* FROM...,适合字段不多的情况 2. 预加载黑科技:ThinkPHP的with()、Laravel的Eager Loading真香 3. 缓存组合拳:Redis存文章+标签哈希,查询直接走缓存 4. 冗余字段术:在文章表直接存标签名的JSON字符串 5. 定时任务+队列:提前生成带标签的文章数据快照

重点说说第三种方案,我们最终采用了Redis的HMSET+HMGET组合:用文章ID作key,标签列表转JSON存value。上线后这个接口的响应时间直接从1.8s降到200ms内,MySQL负载直接掉了一半。

踩坑提醒:JOIN联查时记得给关联字段加索引,否则可能从N+1坑跳进全表扫描的坑...(别问我怎么知道的)

评论24
回复 · 24
未央
未央 新手漫步繁花 · #20 ·
同求,期待更新
小棠
小棠 初级 · #19 ·
同求,期待更新
Vera
Vera 新手 · #18 ·
同求,期待更新
NoahLee
NoahLee 新手 · #17 ·
已解决,谢谢楼主
LunaSong
LunaSong 新手心屿荧途 · #16 ·
感谢分享!
蔡明博
蔡明博 新手 · #15 ·
感谢分享!
倔强的月亮
倔强的月亮 新手赏金猎人 · #14 ·
学到了,顶一下
SilverLake
SilverLake 初级 · #13 ·
已解决,谢谢楼主
EdenLin
EdenLin 初级 · #12 ·
支持了~
Alex
Alex 新手 · #11 ·
学到了,顶一下
FinnLin
FinnLin 新手 · #10 ·
已解决,谢谢楼主
Eden
Eden 新手 · #9 ·
感谢分享!
小鹿
小鹿 初级赏金猎人 · #8 ·
已解决,谢谢楼主
自由的海盐
自由的海盐 新手心屿荧途 · #7 ·
同求,期待更新
安静的草莓
安静的草莓 初级 · #6 ·
写得很清楚,收藏了
KateStar
KateStar 初级 · #5 ·
支持了~
SkyWalker
SkyWalker 新手璃海华章 · #4 ·
写得很清楚,收藏了
郭宁
郭宁 新手 · #3 ·
同求,期待更新
MayaPark
MayaPark 初级 · #2 ·
已解决,谢谢楼主
CoolKid🌸
CoolKid🌸 初级璃梦花海 · #1 ·
同求,期待更新
1 2
微信客服 微信客服