Snowflake Postgres 就是社区版 Postgres——一个关于 Table Access Methods 的误读与澄清

2026-05-24 31 预计阅读时间:1 分钟
来源:postgr.es AI 摘要 原文链接

免责声明:本文为 AI 摘要整理,建议结合原文阅读。摘要可能省略上下文、版本差异或边界条件,不作为官方说明。

预计阅读时间:7 分钟

Christophe Pettus 最近发了一篇更正声明:他此前在周三的文章中声称 Snowflake Postgres 是一个带有私有存储层的 fork,这个说法是错的。事实是——Snowflake Postgres 就是社区版 Postgres,没有魔改存储引擎,没有私有 fork。

这个更正看似只是事实层面的修补,但它背后牵出的技术话题值得深挖:Postgres 的 Table Access Methods(表访问方法)到底是什么?为什么有人会误以为 Snowflake 用了私有存储层?理解这一点,对评估任何"托管 Postgres"服务的真实面目至关重要。

误读是怎么产生的

Postgres 12 引入了 Table Access Methods API,允许第三方实现替代默认的 heap 存储引擎。这意味着理论上,一个云厂商可以写一个专有的 access method,把数据存进自研的列存引擎或对象存储,然后宣称"我们跑的是 Postgres"。

Pettus 原文大概顺着这个思路,推测 Snowflake 的 Postgres 产品用了私有 access method 替换了社区版的 heap 存储。但事实并非如此——Snowflake Postgres 用的就是标准的 heap access method,和你在本地 pg_ctl initdb 出来的数据库一模一样。

这个误读提醒我们:Table Access Methods API 的存在,不等于有人真的在用它替换存储层。 目前生产环境中,绝大多数 Postgres 实例仍然只用默认的 heap。

Table Access Methods 到底是什么

Table Access Methods 是 Postgres 定义存储引擎行为的抽象接口。它决定了:

  • 数据页怎么组织(page layout)
  • 元组怎么插入、更新、删除
  • 索引怎么和表数据关联
  • Vacuum 怎么回收空间

默认且几乎唯一在用的 access method 是 heap——就是大家熟悉的 MVCC 行存储,8KB 页面,自由空间映射(FSM)和可见性映射(VM)那一套。

你可以在 pg_class 中查看任何表绑定的 access method:

-- 查看当前数据库所有表的 access method
SELECT relname, amname
FROM pg_class c
JOIN pg_am a ON c.relam = a.oid
WHERE c.relkind = 'r'
ORDER BY relname;

在标准社区版 Postgres 上,结果里 amname 列只会出现 heap

实操:检查你的 Postgres 是不是"原味"的

不管你用的是 AWS RDS、Azure Flexible Server、Snowflake Postgres 还是自建实例,下面这套检查可以帮你确认存储层有没有被替换:

# 1. 连接到你的托管 Postgres
psql -h your-host -U your-user -d your_db

# 2. 列出系统注册的所有 access methods
SELECT amname, amhandler, amtype
FROM pg_am;

# 3. 在社区版 16 上,你应该只看到:
#    amname  |      amhandler       | amtype
#   --------+----------------------+--------
#    heap    | heap_tableam_handler | t
#    (1 row)
#
#    如果出现其他 amname 且 amtype = 't',
#    说明有人注册了自定义表访问方法。

# 4. 检查是否有表绑定了非 heap 的 access method
SELECT relname, amname
FROM pg_class c
JOIN pg_am a ON c.relam = a.oid
WHERE c.relkind = 'r' AND amname != 'heap';

# 5. 如果上面的查询返回 0 行,你的存储层就是原味社区版。

再补一个更底层的验证——看 pg_settings 中与存储相关的参数是否被魔改:

-- 检查默认 table access method 设置
SELECT name, setting, source
FROM pg_settings
WHERE name = 'default_table_access_method';

-- 社区版默认值是 'heap',source 是 'default'
-- 如果 source 是 'configuration file' 且值不是 'heap',
-- 就要追问厂商改了什么

为什么这个澄清对选型有影响

如果 Snowflake Postgres 真是私有存储层的 fork,那意味着:

  • 社区版工具链(pg_dump、pg_upgrade、逻辑复制)可能不兼容
  • 行为细节可能偏离文档
  • 迁出时数据格式可能无法直接用社区版加载

但既然它就是社区版 Postgres,这些风险就不存在。你可以用标准 pg_dump 导出,用标准 pg_restore 导入到任何其他社区版实例。

不过,"是社区版"不等于"没有差异"。托管服务通常会在 配置、扩展、权限 上做调整:

-- 查看托管服务预装的扩展
SELECT name, default_version, comment
FROM pg_available_extensions
ORDER BY name;

-- 查看哪些扩展被自动 preload
SELECT name, setting
FROM pg_settings
WHERE name = 'shared_preload_libraries';

这些差异是正常的运维层调整,不涉及存储引擎替换,不会影响数据兼容性。

评估托管 Postgres 的清单

下次看到任何"托管 Postgres"产品,用这几步快速判断它的真实面目:

检查项 怎么查 正常结果
表访问方法 SELECT amname FROM pg_am WHERE amtype='t' 只有 heap
默认 access method SHOW default_table_access_method heap
版本号 SELECT version() 标准社区版版本字符串
预装扩展 SELECT name FROM pg_available_extensions 社区版 contrib + 常见第三方
超级用户权限 SELECT current_user, usesuper FROM pg_user WHERE usename = current_user 托管服务通常不给 true superuser

核心原则:只要 pg_am 里没有自定义表访问方法,default_table_access_methodheap,你的数据就存在标准存储格式里,随时可以迁移。

Pettus 的更正本身是个小事件,但它暴露了一个普遍问题——云厂商的营销话术容易让人把"托管"和"魔改"混为一谈。Table Access Methods API 给了厂商魔改的可能性,但截至目前,主流托管服务都没有走这条路。遇到声称"基于 Postgres"的产品,用上面的 SQL 验一遍,比读宣传页靠谱得多。


相关推荐