首页 / 知识库 / python服务端进阶 / 数据库优化-索引与分库分表

05 - 读写分离与缓存

索引、SQL、表结构优化,都是在「单个数据库内部」下功夫。如果单库已经优化到位,压力还是太大,下一步不是急着拆库,而是先借「外部力量」给数据库减负——缓存读写分离

一句话先记住:分库分表之前,先想尽办法「别让请求打到数据库」(缓存)和「把读分摊出去」(读写分离)。

(这两块在《服务端高并发优化》系列讲过原理,这里聚焦「它们在数据库优化路径里的位置」。)


5.1 缓存:让请求根本不到数据库

数据库最怕「反复查同样的数据」。缓存把热点数据放到 Redis(内存),绝大多数读请求在缓存层就返回了,根本不碰数据库。

没有缓存:              有缓存:
 请求 → 数据库           请求 → Redis(命中,2ms)→ 返回
       (每次都查)              └ 未命中才 → 数据库 → 回填缓存

效果:数据库的读压力,可能直接降到原来的 1/10 甚至更低
  • 适合缓存:读多写少、能容忍短暂不一致的数据(商品详情、用户信息、配置)
  • 注意:缓存穿透/击穿/雪崩、一致性问题(见高并发系列第 03 章)

优先级:缓存通常是「单库优化之后」的第一选择,因为它直接砍掉大量读请求,成本又低。


5.2 读写分离:把读分摊到多个从库

大多数系统读远多于写。读写分离让写走主库,读分摊到多个从库:

                应用

        ┌────────┴────────┐
     写 │                 │ 读
        ▼                 ▼
   ┌─────────┐      ┌──────────┐
   │ 主库      │─复制─▶│ 从库1     │
   │ (Master) │─复制─▶│ 从库2     │  读请求分摊
   └─────────┘      └──────────┘

PostgreSQL 原生支持流复制搭建一主多从。

  • 解决的是「读」的扩展:读能力随从库数量增加
  • 最大的坑:主从延迟——刚写完立刻读从库,可能读到旧数据(对策:关键读走主库,见高并发系列第 06 章)

注意边界:读写分离只能扩展读,扩展不了写。如果瓶颈是「写太多」,读写分离救不了,那才要看分库分表。


5.3 分区表(Partitioning):分库分表的「轻量替代」

在真正「分库分表」之前,PostgreSQL 还提供了一个原生、且对应用透明的中间方案——分区表

一张巨大的 orders 表(比如 5 亿行),按时间分区:

  orders (逻辑上还是一张表,应用照常查)
    ├── orders_2023 (物理子表)
    ├── orders_2024 (物理子表)
    └── orders_2025 (物理子表)

查 2025 年的订单 → PostgreSQL 自动只扫 orders_2025 这个分区
  → 不用扫全表(分区裁剪 Partition Pruning)

分区表 vs 分库分表

方面分区表分库分表
位置还在同一个数据库实例拆到多个库/多台机器
对应用基本透明(还是查一张表)应用要感知,通常需中间件
解决单表过大、按范围查询慢单机容量/性能到顶
复杂度低(数据库原生支持)高(跨库查询、分布式事务等)

关键认知:如果你的问题是「单表太大导致查询/维护慢」,但单台机器还扛得住,那 PostgreSQL 分区表往往就够了,不必上真正的分库分表。分区表是「单机内的拆分」,代价小得多。


5.4 优化路径上的位置

把前面所有手段按顺序排一下,你就知道「分库分表」到底排在多后面:

数据库慢/扛不住,优化优先级:

① 索引优化          ← 最先,性价比最高(01-03 章)
② SQL / 表结构优化   ← 改写法和设计(04 章)
③ 缓存             ← 砍掉大量读请求(本章)
④ 读写分离          ← 分摊读压力(本章)
⑤ 分区表           ← 单表太大,但单机够用(本章)
──────────── 以上都不够了,才 ↓ ────────────
⑥ 分库分表          ← 最后的重武器(06-08 章)

核心思想:分库分表是「架构级手术」,会带来一堆新问题。前面五步能解决就绝不上第六步。 现实中,绝大多数系统在前五步就够了。


本章小结

你要记住要点
缓存让读请求根本不到数据库,砍读压力,成本低
读写分离写主库读从库,扩展读能力;扩展不了写
分区表单机内拆大表,对应用透明,代价远小于分库分表
优化路径索引→SQL→缓存→读写分离→分区表→(最后)分库分表

下一章预告:如果前面所有招都用尽了还扛不住,才轮到分库分表登场。它到底解决什么问题?为什么说它是「重武器」?


上一章 ← 04 - SQL 与表结构优化 | 下一章 → 06 - 为什么要分库分表