内容提要
文章讨论PostgreSQL处理大量对象的局限。评论者分享:3500个schema、每个800张表时,pg_upgrade需48小时以上、128GB内存,改用并行pg_dump迁移仅4小时。作者建议多租户应使用多数据库或单表加行级安全,而非大量schema。
延伸解读
多租户架构的替代方案
文章指出,使用大量schema进行多租户隔离在租户数量多时会遇到严重性能问题。作者建议,对于3500个租户的场景,应改用多个数据库(便于分片到不同机器)或单表加行级安全策略。这为面临类似困境的团队提供了明确的架构调整方向。
pg_upgrade的耗时与内存消耗
评论者分享,在3500个schema、每个800张表的环境下,pg_upgrade需要48小时以上并消耗超过128GB内存。作者回应称,即使有数百万张表也不应如此耗时,可能与大对象有关。这提示读者,在对象数量极多时,升级工具可能成为瓶颈,需提前评估资源。
并行pg_dump迁移的实践与代价
为绕过pg_upgrade的瓶颈,评论者采用按schema并行pg_dump的方式,将迁移时间从预计2天以上缩短到约4小时。但每个pg_dump进程消耗14GB内存,需要1TB内存的机器。这种方法虽快,但资源需求高,且评论者不推荐在生产环境直接使用。
日常运维的连锁反应
大量对象还会拖慢autovacuum的统计扫描,迫使连接池每30秒全刷新以缓解catcache内存问题,旧版统计收集器也会频繁写盘。这些细节表明,对象数量膨胀不仅影响升级,还会波及日常维护、连接管理和I/O,增加整体运维复杂度。
Q&A
PostgreSQL 处理大量表时有哪些性能问题?
PostgreSQL 并不擅长处理大量对象。当表数量很多时,每个连接访问这些表可能需要 300MB 以上的内存,pg_upgrade 可能需要数天时间,autovacuum 扫描统计信息需要数分钟,连接池需要频繁刷新以避免 catcache 内存消耗问题,旧的统计收集器进程会因定期刷新而大量占用磁盘。
pg_upgrade 在表数量多时表现如何?
pg_upgrade 在表数量多时可能非常慢。有案例显示,在 3500 个 schema、每个 800 张表(约 280 万张表)的情况下,pg_upgrade 需要 48 小时以上,并消耗超过 128GB 内存才能避免 OOM。作者自己测试 20000 张表时,pg_upgrade --link 也花了二十多分钟。
如何加速 PostgreSQL 大版本升级?
可以采用并行 pg_dump 按 schema 迁移。例如,从 PostgreSQL 11 升级到 14 时,使用 64 个并行 pg_dump 分 3 批处理,每批约 20 多个 schema,每个 pg_dump 消耗 14GB 内存,需要 1TB 内存的机器。整个 dump/restore 过程约 4 小时完成,远快于预期 2 天以上的 pg_upgrade。
多租户应用应该用 schema 还是多数据库?
如果租户数量很少,使用 schema 是可行的。但当租户数量很多(如 3500 个)时,应使用多个数据库(可以将分片放在不同机器上)或使用单个(可能分区的)表加上行级安全(RLS)。
PostgreSQL 表数量增加时性能下降是线性的吗?
大多数情况下,痛苦随表数量线性增长,但某些元数据查询连接两个大的目录表时,性能下降会更快。例如,20000 张表时,如果只有 10000 张,痛苦减半。何时变得难以忍受取决于资源(内存)或可接受的查询时长(元数据查询)。
大量表对 PostgreSQL 的 autovacuum 和连接池有什么影响?
autovacuum 需要数分钟来扫描统计信息并判断是否需要运行。连接池需要配置为每 30 秒完全刷新,以避免 catcache 的内存消耗问题,但在高峰时段有时仍不够。旧的统计收集器进程会因定期刷新而大量占用磁盘。