先说结论
多语言站的性能问题,通常不在"代码慢",在"页面数量乘以语种数"。33 个语种 × 每个 2000 页 = 6.6 万个 URL,任何全表扫描都会变慢。
sitemap 为什么必须分片
协议限制单文件 5 万条 / 50MB。多语言站很容易逼近上限。
做法:
- 每个语种独立 sitemap:
/sitemap-ja-1.xml - 索引文件
/sitemap.xml列出所有分片 - 每片 5000 条,留余量
- 内容更新时只重建受影响的分片
首页查询的三个坑
- N+1:首页列出 12 个产品,每个都查一次分类 → 13 次查询
- 翻译 JSON 过大:一条内容存 33 个语种的 JSON,首页列表全查出来会很慢
- 排序字段无索引:按发布时间排序但没建索引
解法:
- 列表查询只取当前语种需要的字段
- 分类用 join 一次取回
(lang, status, published_at)联合索引
缓存策略
| 层 | 内容 | 失效方式 |
|---|---|---|
| 文件缓存 | 语言列表、站点配置 | 保存配置时清 |
| 页面缓存 | 首页、分类页(可选) | 内容发布时按语种清 |
| 浏览器缓存 | 静态资源(带版本号) | 文件名变化 |
压测方法
不要凭感觉。用脚本跑:
- 首页、分类页、详情页各 100 次并发
- 记录 P95 响应时间
- 看 MySQL 慢查询日志
- 逐步加压,找到拐点
实测 2C4G:首页 100 并发 P95 约 180–300ms;加到 500 并发 P95 到 600ms 以上,瓶颈在 MySQL 而不是 PHP。生产建议单站 2C4G,日 PV 一万以内不必加缓存层。