Q63: 如何优化数据库查询?
核心结论
数据库查询优化的核心,不是背多少 SQL 技巧,而是先弄清楚:
- 哪些查询最贵
- 为什么贵
- 能不能减少查询次数
很多数据库问题不是“SQL 写得不够花”,而是系统把不该落到数据库的压力全打到了数据库上。
一、先判断问题是不是查询本身
常见数据库慢,可能来自:
- SQL 语句差
- 索引不对
- 表设计不合理
- 查询次数太多
- 热点数据没缓存
如果不先区分原因,容易只会一味加索引。
二、减少查询次数通常比优化单条 SQL 更值
常见收益很高的做法包括:
- 批量查询
- 缓存热点数据
- 合理预加载
- 避免 N+1 查询
很多系统真正的瓶颈,不是某一条 SQL 太慢,而是同一类小查询打得太多。
三、索引优化要围绕真实访问模式
索引不是越多越好。
设计索引时应该先问:
- 这条查询最常见的 where 条件是什么
- 是否有排序和分页
- 是否只需要覆盖索引
如果和真实访问模式不匹配,再多索引也没用,还会放大写入成本。
四、深分页、模糊查询和大范围扫描要特别小心
这几类查询最容易在业务做大后出问题。
常见改法包括:
- 用游标或基于主键翻页替代深分页
- 把搜索交给更合适的索引或搜索层
- 让报表和在线主库隔离
不要指望一条“万能 SQL”同时搞定在线查询和分析查询。
五、读写分离和缓存不是银弹
它们确实常用,但前提是:
- 业务能接受读延迟
- 缓存失效策略清晰
- 不会制造新的热点
否则只是把问题换个地方爆发。
六、查询优化必须和表结构一起看
如果表结构本身不适合查询,例如:
- 超宽表
- 高频字段和低频字段混在一起
- 大量 JSON 难以过滤
那再怎么改 SQL 也只能止损。
七、工程上更稳妥的优化顺序
常见做法是:
- 先抓慢查询和高频查询
- 先减查询次数
- 再调整索引和 SQL
- 最后再考虑拆表、读写分离和搜索层
这样通常比一上来重构数据库更有效。
八、常见误区
1. 数据库慢就先加索引
不一定。可能真正的问题是查询模式或数据模型错了。
2. SELECT * 改成列名就算优化了
有时有用,但往往不是主要瓶颈。
3. 所有慢查询都应该进缓存
缓存可以缓解一部分问题,但会带来一致性和回源压力,需要看场景。
参考资料
- 慢查询分析、索引设计和在线数据库治理实践资料
