← 中文资源

简体中文版本

写放大

写放大是物理写入字节与逻辑变更字节之比,由索引、复制、日志和存储压缩共同驱动。

阅读英文原文

一次逻辑写,多次物理写

一条 INSERT 可能触及多个位置:预写日志记录变更,表堆写入新元组,每个索引写入条目,副本也可能收到相同记录。后台进程随后写脏页和检查点。物理字节可能是逻辑行大小的数倍。

SELECT pg_stat_database.datname,
       pg_size_pretty(pg_stat_database.temp_bytes) AS temp_bytes,
       pg_stat_database.xact_commit
FROM pg_stat_database
WHERE datname = current_database();

具体比例取决于行宽、索引数量、填充因子和工作负载。窄行加三个索引和副本,放大可能远高于宽行无索引。要用真实 schema 和工作负载测量,单表估算会误导。

索引用读速度换写成本

每个索引都要在插入、更新、删除时维护。很少使用的索引仍然消耗写带宽和存储。用 pg_stat_user_indexes 检查索引使用情况,删除真实查询不用的索引。写密集表通常更适合少量高选择性索引,而不是许多窄索引。

更新不是免费的

PostgreSQL 更新会创建新行版本并把旧版本标记为待清理。更新大 JSON 文档或宽行会重写整行,即使只改一个字段。规范化热字段、避免无意义更新,并在业务允许时批量合并小变更。对同一行的频繁更新还会造成膨胀和 vacuum 压力。

何时使用这个视角

当写吞吐、SSD 寿命、复制延迟或检查点延迟成为问题时,用写放大来推理。优点是把 schema 与批处理决策变成可比较的具体成本;缺点是需要测量而不是直觉。与只优化查询延迟相比,降低放大通常提升系统整体余量,但删除索引可能让读取变慢。