你在云上跑过一个几十 GB 的分析查询,第一次闷了几十分钟,第二次再跑突然几秒钟就出来了。大多数玩 PostgreSQL 的人第一反应是“shared_buffers 缓存热了”,但如果底层用的是大云海山数据库(He3DB)这种存算分离形态,真正在背后干脏活累活的,往往是 FileCache。这篇文章我想把 He3DB FileCache 机制的来龙去脉讲透,包括它到底缓存什么、为什么不直接用 Page Cache、命中率和淘汰策略怎么设计、参数怎么调、上线后会踩哪些坑。适合正在折腾云原生数据库选型、想把 PostgreSQL 业务迁到共享存储架构,或者单纯好奇“为什么同一个查询第二次跑得快这么多”的 DBA 和后端开发者。
1. 先搞清楚背景:He3DB 为什么要做 FileCache
1.1 大云海山数据库到底是什么形态
先说清楚 He3DB 的定位:这是一款整体延续 PostgreSQL 生态的云原生数据库产品,对外协议兼容 PG,所以应用层几乎不用改就能接入。但它和传统“一台机器上跑一个 PG 实例,数据落在本地磁盘”的部署方式有本质区别。He3DB 做了计算与存储分离:计算节点只负责 SQL 解析、执行计划、事务处理,真正存放数据的是一套远端共享存储。也就是说,底层的那份数据文件并不在计算节点的本地磁盘上,而是在远端。
这种架构最直观的红利是弹性。计算节点可以独立扩缩容,存储也不绑死在单机上,数据可以多副本冗余,底层存储故障不影响计算节点。传统 PG 碰到磁盘满了只能扩盘或者做迁移,存算分离方式下这些问题都被一层共享存储挡在下面,对业务是透明的。
但代价也很实在:每一次数据页访问都要走网络。读一个 8KB 的页面,本地盘可能几十微秒就完成了,远端存储再快也要经历网络 RTT,通常是百微秒到毫秒级别。如果每个查询都老老实实去远端读页面,再好的执行引擎也会被 IO 延迟拖死。FileCache 在这里承担的角色,就是给计算节点配一个“本地仓库”,把远端经常访问的热数据页缓存到本机存储上,尽量让热点查询在本地就能拿到数据。
1.2 没有本地缓存时,一条查询的数据路径有多长
为了说明 FileCache 的价值,我拆一下最朴素的数据访问路径。假设 SQL 要读某张表的一批页面,在没有 FileCache 的情况下,一次页面请求大概需要经历这么几步:
- PostgreSQL 的 buffer manager 去 shared_buffers 里找目标页,没命中。
- 调用存储管理接口,把请求发给远端存储客户端。
- 客户端把读请求编码、加密、通过网络发送到远端存储服务。
- 远端存储从底层磁盘或者分布式存储集群中取出页面。
- 数据再经网络返回计算节点,做校验、解密。
- 页面进入 shared_buffers,返回给查询执行层。
这条链路里每一步都有实际开销。网络抖动、存储服务端排队、协议解析,都可能让单次页面读取变成几毫秒。如果是一个全表扫描或者大范围索引扫描,涉及上万甚至上百万个页面,这种延迟会直接叠加成分钟级的差距。
所以 FileCache 的出现本质上是在回答一个问题:既然网络读取这么贵,能不能在计算节点本地保留一份最近用过的页面副本?下次再读同样的数据,直接从本地存储返回,把远端网络 RTT 从关键路径上拿掉。这就是 FileCache 最核心的定位——一层位于计算节点本地、以数据库页面为缓存单位的应用层缓存。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. FileCache 的核心机制与设计选择
2.1 缓存粒度:为什么按“页”管理,而不是按文件或整表
FileCache 在设计上最需要先确定的就是缓存粒度。你可以按整张表文件缓存,也可以按数据块缓存,还可以按 PostgreSQL 的页面(默认 8KB)缓存。He3DB 的实现是走页面级粒度,这个选择在工程上很自然,原因有三点。
第
