正在载入社区…
正在载入社区…
正在载入帖子…
长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长
长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长简介长
令牌 30 分钟、请求头要逐字对齐、写入不幂等、限流按账号算。四条都是我自己撞出来的。
/ bilibili https://www.bilibili.com/video/BV169HP6MEZo
一个外链播放器测试
覆盖公式、Mermaid、代码、表格、链接、多语言、emoji、不同比例图片与评论区的完整验收帖。
C const apple = 1; if (apple != 1){ printf("this is impossible !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); return 0; }
《逻辑哲学论》最后说,理解它的人必须把梯子丢掉;问题是丢掉之后还剩下什么。
不用文字提示,地形、光线和可交互物就能告诉玩家往哪走、什么值得试。
因为那些独白不是人物的总结陈词,而是他们在语言里试探自己下一步要成为谁。
很多所谓 PostgreSQL 写优化,最后都变成一句“加个索引”或者“把 关掉”。这两件事都可能有收益,但也都可能把问题挪到别处。
我习惯先把一次写入拆成几块成本:
优化之前,先确认哪一块真的贵。 看总时间,不要只看 mean; 和 wait events 看排队;、checkpoint 日志看 WAL 与刷盘;表膨胀和 autovacuum 看长期成本。
下面这些点,是我认为最值得先想的。
关闭同步提交,确实能把“等 WAL flush”从提交路径上拿掉,延迟会好看很多。但它换掉的是持久性:
数据库崩溃时,最近一段时间已提交的事务可能丢失。
所以它适合:
不适合:
如果只是某类批量导入能接受丢失,可以用事务级设置,不要全局一刀切:
SET LOCAL synchronous_commit = off;另一个常见误解是“关掉同步提交就没有 group commit 了”。实际上 group commit 仍然存在;只是提交不再等本地 flush。真正要观察的是 WAL 生成量、checkpoint 频率和崩溃恢复时间。
每个索引都要在 INSERT/UPDATE/DELETE 时维护。索引越多,写越慢,WAL 越大,缓存越容易被污染。
先找“几乎不写、但占着维护成本”的索引:
SELECT schemaname, relname, indexrelname, idx_scan, pg_size_pretty(pg_relation_size(indexrelid)) AS sizeFROM pg_stat_user_indexesORDER BY idx_scan ASC, pg_relation_size(indexrelid) DESC;不一定是垃圾:唯一约束、外键支撑、很少跑但很关键的报表查询都可能需要它。要结合业务窗口和约束判断。
常见做法:
不要为了“以后可能会查”给每个字段都加索引。写路径的账,最后会以 WAL、锁和 vacuum 的形式还回来。
连接数上去,数据库并不是线性变快。每个连接都有内存、上下文切换和锁竞争成本。真正要控制的是:
一个常见故障是:应用侧连接池很大,数据库侧 也很大,结果大量连接在等锁、等 IO,吞吐反而下降。
我更喜欢从较小的池开始,观察:
如果 CPU 没满、池在排队,先查慢查询和长事务;如果 CPU 满了,再加连接通常只会更糟。
还有一点:不要在事务里做网络调用。发邮件、调外部 API、写对象存储,都应该移出事务。事务持有时间越长,快照越老,vacuum 越难推进,锁冲突越多。
逐条 INSERT 的成本,很大一部分在往返和提交,而不是行本身。把 100 条合成一条 multi-row INSERT,或者用 COPY,通常能明显降低单位写入成本。
但批量不是越大越好:
一个实用的做法是固定“行数上限 + 时间上限”,比如每批最多 N 行或每 M 毫秒 flush 一次。批量写入还要考虑:
批处理最怕的是“为了吞吐牺牲可观测性”。批次大小、flush 延迟、失败率、队列深度都要有指标。
点赞数、阅读数、库存、余额这类字段,容易变成单行热点。每次都 ,高并发下会在一行上排队。
可选方案:
分桶不是银弹:它把写竞争换成了读聚合和后台合并成本。要不要做,取决于读写比和一致性要求。
读写分离能降低主库读压力,但会引入复制延迟:
常见处理:
缓存也是同理。缓存不是数据库,缓存是“允许短暂不一致的读优化”。把缓存当唯一事实源,最后一定会在失效、回滚和重建上付出更大代价。
分片能解决单库写入上限,但也会把事务、join、唯一约束、运维复杂度一起拆开。大多数中小系统的问题,不是“必须分片”,而是:
分区更适合:
它不自动让写入变快。分区键选错,反而会让跨分区查询和唯一约束更痛苦。
写路径优化至少看这些:
里, 高但 mean 低的查询,可能是高频小查询;mean 高但 calls 少的,可能是重聚合。两者优化方式完全不同。
PostgreSQL 写路径优化,本质上是在几个约束之间做交换:
没有一组参数适合所有系统。先算账,再动手;先证明瓶颈,再谈优化。
文中的数字和场景均为说明性示例,不代表任何线上系统的真实数据。
© 2026 · fatfish.world 大肥鱼世界
评论
登录后可以评论,也可以回复某条评论。
还没有评论
说说你的看法,或者指出文中没有说清的地方。