Django + Vue 项目实战:我把接口响应从 1.8 秒压到 200 毫秒,这 9 个步骤和踩坑记录你拿去用

🔑 关键词:Django, Vue, 接口优化, 项目实战, 性能调优

📖 摘要:一个业余开发者用 Django + Vue 做的小项目,日活 300 左右,接口慢到被用户骂。本文记录我从 1.8s 优化到 200ms 的 9 个具体步骤,包括 select_related、Redis 缓存、索引失效等真实踩坑,附前后数据对比。

先说背景,我这个项目有多慢

图片

去年年底我用 Django 3.2 + Vue 2 写了个小型商品管理系统,给自己和朋友用,日活大概 300 人左右。 服务器是腾讯云 1 核 2G 的轻量,MySQL 5.7,Redis 都没装,就直接跑着。 结果上个月朋友抱怨说“点一下商品列表要等半天”,我自己测了一下 /api/products/ 这个接口,平均响应 1.8 秒,最慢的一次 4.2 秒。 我当时就懵了,因为数据量才 2 万多条商品,按理说不该这么慢。 用 Django Debug Toolbar 一看,好家伙,一个请求打了 187 次 SQL 查询,全是 N+1。

我试过的几种方案,效果差别很大

图片

最开始我以为是数据库不行,想换 PostgreSQL,但迁移太麻烦就放弃了。 然后我试了加索引,给 product 表的 category_id 和 created_at 加了普通索引,响应从 1.8s 降到 1.2s,有点用但不够。 接着我用了 DRF 的 select_related 和 prefetch_related,这个效果最明显,直接从 1.2s 掉到 600ms 左右。 但还有问题,序列化的时候我把整个 model 都返回了,字段太多,JSON 有 200 多 KB。 后来我换成 values() 只取需要的字段,又降到 400ms。 再后来上了 Redis 缓存热点数据,才到 200ms 左右。 说实话,我一开始还想上 Elasticsearch,后来发现数据量太小,MySQL 全文索引就够用了,差点白折腾。

图片

具体 9 个步骤,你照着做就行

  1. 装 django-debug-toolbar,在 settings.py 的 INSTALLED_APPS 里加上,然后看哪个接口 SQL 最多。
  2. 把 ModelSerializer 里所有外键都加上 select_related,多对多用 prefetch_related,我加了之后 SQL 从 187 次降到 12 次。
  3. 给常用的查询字段加索引,比如 category_id、status、created_at,注意别加太多,写操作会变慢。
  4. 用 .values('id', 'name', 'price') 代替返回整个对象,JSON 体积从 220KB 降到 45KB。
  5. 分页,每页 20 条,用 Django 的 Paginator,前端也配合做懒加载。
  6. 装 Redis,用 django-redis 做缓存,把商品分类和首页推荐缓存 5 分钟,命中率大概 85%。
  7. 缓存更新用 Celery 异步任务,避免直接删缓存导致雪崩,我设了随机过期时间 300±60 秒。
  8. Nginx 开启 gzip,对 JSON 响应压缩,体积又小了 60%。
  9. 把 DEBUG 设为 False,然后用 whitenoise 处理静态文件,不然 404 能把你搞疯。

图片

踩过的坑,每个都让我想砸键盘

图片

第一个坑:select_related 不能用于多对多,我一开始写错了,结果报错说“Invalid field name”,查了半天文档。 第二个坑:prefetch_related 会额外产生查询,如果没配合好,SQL 数量反而变多,要先用 debug toolbar 看。 第三个坑:MySQL 索引对 like '%关键词%' 完全无效,我一开始用 icontains 搜索,加了索引也没用,后来改成全文索引才解决。 第四个坑:Redis 缓存雪崩,有次我批量更新商品,缓存全过期了,数据库瞬间被打满,服务器直接卡死。 第五个坑:Django 的 DEBUG=False 后,static 文件全部 404,我折腾了一晚上才想起来用 whitenoise。 还有一个不算坑的坑:我改完代码忘了跑 migrate,线上直接 500,被朋友笑了好久。

最后的数据和一点个人感受

图片

优化完之后,接口平均响应 180ms,P95 是 350ms,服务器 CPU 从 80% 降到 15%,内存从 1.6G 降到 700M。 用户投诉从每天 5 条降到 0,但我还是留了个尾巴:没做监控,后来有一次慢查询是过了三天才发现的。 所以如果你也在做类似的小项目,我的建议是:先量再优,别一上来就微服务、分库分表。 我这个项目总共就 2 万条数据,单体 + 索引 + 缓存 + 分页完全够用。 那些花里胡哨的架构,等日活过万再说吧。 对了,我后来用 Sentry 做了错误监控,免费版够用,推荐你也装一个。

🏷️ 标签: