跳转至

数据库里的 WebAssembly — UDF、内联处理与基准测试

1. 这一章讲什么

数据库的老难题:用户想往库里塞自己的逻辑(自定义函数、存储过程), 但传统做法要么慢(解释型 PL/pgSQL),要么危险(原生 C 扩展,一个空指针整个库崩)。 这一章论证 Wasm 是第三条路——沙箱模块在数据库进程内跑,近原生速度、崩了也炸不到库, 而且一份模块三个库通用。本章是全书基准测试最扎实的一章:给了硬件环境和完整的对比表。1

2. 顶层全景

  问题:自定义逻辑的三难(慢 / 危险 / 平台绑定)
      │
      ▼
  Wasm UDF:沙箱 + 近原生 + 跨库可移植
      │
      ├── PostgreSQL:pg-wasm 扩展(运行时嵌进库进程)
      ├── SQLite:WasmEdge/Wasmer 嵌入(边缘设备场景)
      └── ScyllaDB:摄入层/查询层/代理层三处插模块
      │
      ▼
  基准:PG 比 PL/pgSQL 快 30–40%、比 C 慢 10–20%
      SQLite 达 C 的 90%;ScyllaDB 内联聚合 -15–25% 延迟
      │
      ▼
  落地:预编译、轻量运行时、限额、结构化日志、特性开关、版本注册表

图说:问题 → 方案 → 三个库的各自接法 → 数字 → 纪律,五步走完本章。

3. 核心原理

3.1 为什么传统扩展不够用

传统数据库扩展(原生 C 写的 UDF/扩展)的三宗罪,书里列得很直白: 平台绑定(换硬件要重编)、内存不安全(段错误能崩掉整个数据库进程)、 多租户难管(租户代码和库同生共死)。2

Wasm 版本的对照表(书里的 Table 11.1,四行):

维度 Wasm 对传统 UDF 的改进
可移植 模块跨数据库、跨硬件直接复用
安全 沙箱执行,崩了也隔离在模块内
性能 编译型字节码,近原生,快过解释型 UDF
灵活 Rust/C++/Zig 任选,甚至实验性的 Python/Go/TS 编译器

更深一层的变化书里点破了:这让数据库逻辑也能进 CI/CD——版本化、测试、回滚, 以前是应用代码的专利,现在存储过程式的逻辑也配拥有。3

3.2 PostgreSQL:pg-wasm 的接法

架构三件套:4

  1. Wasm 运行时(如 Wasmtime)嵌进 PostgreSQL 进程;
  2. 一座桥:SQL 类型 ↔ Wasm 函数的参数映射;
  3. 模块注册成 UDF,用 SQL 直接调。

书里的完整最小例子,Rust 写加法:5

#[no_mangle]
pub extern "C" fn rust_add(a: i32, b: i32) -> i32 { a + b }
rustc --target wasm32-wasi rust_add.rs -o rust_add.wasm

CREATE FUNCTION rust_add(a int, b int) RETURNS int
  AS 'file:///modules/rust_add.wasm' LANGUAGE wasm;

SELECT rust_add(5, 3);  -- 返回 8

基准结论(书里的 Table 11.3):Wasm 比 PL/pgSQL 快 30–40%,比原生 C 慢 10–20%—— 中间地带:比脚本语言快得多,比原生慢一点,换来沙箱。 代价也要认:每个 Wasm UDF 实例有 10–20MB 的运行时内存开销;简单查询上 PL/pgSQL 反而可能赢(初始化开销低)。6

3.3 SQLite:嵌入式的 Wasm

SQLite 跑在手机上、IoT 里,原生不支持 UDF——正适合 Wasm 补位: 把 SQLite 和轻量运行时(WasmEdge 给边缘设备、Wasmer 求通用)编译在一起, 模块注册成虚拟表函数或 UDF。7

书里的传感器归一化例子(华氏转摄氏,公式可见可验):8

#[no_mangle]
pub extern "C" fn normalize_sensor(value: f32) -> f32 {
    (value - 32.0) * 5.0 / 9.0
}

基准:Wasm 达到原生 C 的 85–95%,内存代价 +20–30MB 运行时。 结论:全原生插件不让装的嵌入式场景,Wasm 几乎是唯一解。9

3.4 ScyllaDB:在摄入点内联计算

ScyllaDB 是 C++/Seastar 写的分布式 NoSQL,百万级 QPS 的基因。 它的痛点正好和 Wasm 对症:传统上大数据分析要把数据搬出去(Spark/Flink), 网络延迟 + 序列化 + 资源争抢三笔账;Wasm 让逻辑直接在摄入点跑。10

三个插入点:11

插入点 干什么
摄入层 写入前过滤/转换/校验,业务规则不打扰上游
查询层 查询时跑轻量分析函数、结果富化
代理层 客户端和库之间的 sidecar,多租户沙箱

四个用例模式:自定义过滤器(只收满足领域条件的记录)、写入时内联归一化、 摄入时预计算聚合(省后面的查询)、轻量规则触发告警。12

3.5 基准测试:全书最认真的一次测量

测试环境书里给全了:16 核 Ryzen 9 5950X、64GB 内存、NVMe、Ubuntu 22.04, Wasmtime 15.0 / PostgreSQL 16 / SQLite 3.45 / ScyllaDB 5.4, 负载用 TPC-H(分析型)和 TPC-C(事务型,模拟下单、付款这类业务),四个指标(延迟、吞吐(每秒处理多少操作)、内存、CPU), 冷/热缓存各跑、五次取平均。13

三组结果(书里的表,数字照录):

PostgreSQL(聚合查询延迟:PL/pgSQL 180ms / C 80ms / Wasm 96ms; 向量数学 UDF:230 / 120 / 138;内存开销:Wasm 每实例 +10–20MB):14

引擎 Wasm 的位置 关键数字
PostgreSQL 比 PL/pgSQL 快、比 C 稍慢 比 C 慢 10–20%,比 PL/pgSQL 快 30–40%
SQLite 嵌入式唯一选项 达原生 C 的 ~90%,+20–30MB 内存
ScyllaDB 内联聚合替代外部聚合器 延迟 -15–25%,吞吐 100k→140k/秒,零数据传输成本

ScyllaDB 那组最说明问题:外部 Python 聚合器平均 14ms、峰值 25ms、吞吐 10 万/秒; 内联 Wasm 平均 11ms、峰值 18ms、吞吐 14 万/秒——而且「数据传输成本」一栏, 外部方案是 High,Wasm 是 None。15

主线例子(把账算给你看):一条物联网温度事件流进 ScyllaDB。 旧路:事件先落库,外部服务轮询扫表,发现超阈值再告警——轮询周期就是延迟下限,秒级。 新路:Wasm 模块在摄入层拦截,temperature > 80.0 当场 trigger_alert, 响应从秒级到毫秒级;同一模块可以横向铺到每个分片(shard)上,没有中心化瓶颈。16

注意这组数字的读法:它们是「方向性实测」,环境里每项(硬件、版本、数据分布)都会移动 绝对值;可移植的是排序(PL/pgSQL < Wasm < C)和成本形态(Wasm 用 10–20MB 内存换沙箱)。

3.6 四个生产用例速览

用例 库 Wasm 的角色 书里的收益数字
JSON 校验 UDF PostgreSQL 解析+校验+归一化 比 PL/pgSQL 快 30–50%
实时告警 ScyllaDB 摄入层阈值/滑动窗口判断 秒级 → 毫秒级
行级访问控制 SQLite 引擎内按用户角色过滤行 规则前端绕不过
二进制日志正则 通用 Rust regex 引擎嵌进解析工具 快 40–60%,模块约 200KB

17

3.7 部署纪律七条

  1. AOT 预编译:模块一律提前编译优化(wasm-opt -O3),拒绝运行时动态编译;
  2. 轻量运行时:Wasmtime(生产标杆)/ WasmEdge(边缘);Lucet 标注为 legacy;
  3. 限额:内存上限(模块内 memory(1) 或宿主 cap)、执行超时、Tokio 异步超时包裹;
  4. 结构化日志:模块名/版本、时间戳、截断的出入参、异常、进出内存——ELK/Loki 集中, 打租户/分片标签;
  5. 特性开关:金丝雀发布(先放一小撮查询)、按租户灰度、定时自动回滚;
  6. 安全:WASI 能力审计到最小、非 root 运行、按租户隔离、wasm-objdump 定期扫二进制;
  7. 版本注册表:像容器镜像仓一样管模块——SHA-256 哈希(把任意数据算成固定长度指纹的函数)、工具链、兼容版本、依赖声明, 支持回滚。18

4. 作者的判断与证据

  • 基准章节:测试环境交代完整,数字内部自洽,是全书证据等级最高的一节; 但仍是单次实验,没有方差和标准差(衡量数据分散程度的量),五次平均的冷热缓存设计是认真的但不算严格;
  • 「Wasm UDF 不能访问未授权内存」:机制上成立,前提是宿主正确配置 WASI 能力—— 书在后面安全节也承认了这条;
  • 「数据库逻辑的 CI/CD」:判断有洞察力,且正在成真(Turso/MotherDuck 等已在这条路上)。

判断(我们的,不是书里的): 本章有一个没点破的结构事实:三个数据库的 Wasm 整合, 成熟度完全不同。pg-wasm 是社区扩展而非官方能力;SQLite 的 Wasm 集成主要是 「把 SQLite 编译成 Wasm 跑在浏览器」(方向恰好相反!);ScyllaDB 的 Wasm 支持 实际是 sidecar/代理模式而非库内 UDF——书里「native UDF framework」标为未来方向, 说明今天还不存在。读这章要把「路线图」和「现货」分开。 如果错,会错在: 如果 2025–2026 年间某家数据库把 Wasm UDF 扶正为官方一等能力 (DuckDB 系动作最快),「成熟度分层」的判断就需要更新——但方向(库内沙箱执行)不会变。

5. 边界与局限

  • pg-wasm 非官方:书里没强调它是第三方实验扩展,生产采用要看维护状态;
  • SQLite 一节的方向混淆:业界 SQLite+Wasm 的主流是「SQLite 编译到 Wasm 跑浏览器」 (如 wa-sqlite),本章讲的「Wasm 模块进 SQLite」是较冷的路线;
  • 基准没有方差:五次平均,无标准差、无置信区间;「90% of native」这类数字 应读作点估计;
  • 事务语义没碰:Wasm UDF 在事务里失败怎么办、和数据库锁的交互,本章零讨论。

6. 可带走的

  1. 数据库扩展的三难:慢(脚本)、险(C 扩展)、绑定(平台)——Wasm 同时解三个,代价是 10–20MB 内存 + 10–20% 速度。
  2. 性能排序记死:PL/pgSQL < Wasm < 原生 C;嵌入式场景 Wasm 常是唯一选项。
  3. ScyllaDB 的账:内联聚合延迟 -15–25%、吞吐 100k→140k/秒、数据传输成本归零。
  4. 「数据库逻辑进 CI/CD」是范式级变化:版本化、灰度、回滚,存储过程也配。
  5. 三个插入点背下来:摄入层(写前)、查询层(读时)、代理层(中间)。
  6. 部署七条:AOT、轻量运行时、限额、结构化日志、特性开关、WASI 最小化、版本注册表。
  7. 基准数字都是「点估计」,移植排序不移植绝对值。
  8. 把「路线图」和「现货」分开读:本章不少能力标着 future directions。
  9. 内存上限 + 执行超时是多租户的生命线,不是可选项。
  10. 生态工具认八个名字:Wasmtime、WasmEdge、Wasmer、Extism、pg-wasm、waPC、Wizer、Wasm Workers Server。

8. 加厚一:三个库的集成细节补全(原书细节)

PostgreSQL 侧,注册之后还有两件运维事:观测靠 pg_stat_statements 跟踪 Wasm UDF 的调用耗时,运行期错误进日志扩展;资源约束场景要给运行时盯内存—— 因为每个 UDF 实例 10–20MB 的开销,在小型实例上不是小数。19

SQLite 侧,集成的形态是「编译在一起」:SQLite 和 WasmEdge/Wasmer 编进同一个 二进制,模块注册成虚拟表函数或 UDF。归一化那个例子在查询里就地把华氏转成摄氏, 应用层少搬一层数据——嵌入式场景的「算近数据」全在这一句里。20

ScyllaDB 侧,书里列的四种扩展模式值得记住,因为它们就是所有流式系统的 通用菜单:写入时过滤(只收满足领域条件的记录)、写入时转换(归一化/富化)、 写入时预聚合(计数、均值,省后面的查询)、轻量规则告警。 告警模式的触发条件书里给了个具体样例:temperature > 80.0 就 trigger_alert。21

9. 加厚二:未来方向(原书第 11 章末节)

书里点了四个方向,两个已经长出产品:

  • 内存数据库 + Wasm:数据全在内存,Wasm 模块直接当算子跑,响应 <1ms, 面向游戏遥测、欺诈检测;
  • 云原生数据库内建 Wasm:Turso(边缘 SQLite)、MotherDuck(DuckDB 系)、 EdgeDB 在探索把 Wasm 当可插拔计算层——「数据库逻辑进 CI/CD」的落地形态;
  • SQL 里跑模型推理:SELECT predict_churn(features) 这种写法, ONNX/TensorFlow Lite 模型编译进 Wasm,免去外部 Python 服务一跳;
  • SQL + Wasm 混合流水线:SELECT 的 WHERE、ORDER BY 里直接嵌 Wasm 函数, 书上给了完整样例查询。22

判断这四个方向的成熟度,书自己的措辞给了线索:ScyllaDB 的 native UDF 写的是「could evolve toward」——还没发生。读这章时要给每条标上「现货/在路上」。23

10. 原文地图

主题 原书章 原文位置
传统扩展三宗罪 WebAssembly in Databases text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:161(搜「Platform-specific」)
Wasm 四优势表 同上 text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:219(搜「Wasm modules can be shared」) · text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:241(搜「Benefits of Wasm over Traditional UDFs」)
存储过程的替代/增强 同上 text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:317(搜「Replacing or Augmenting」)
pg-wasm 架构与 rust_add 例 同上 text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:421(搜「pg-wasm extension」) · text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:439(搜「rust_add」)
pg-wasm 基准 同上 text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:465(搜「20-30% better latency」)
SQLite 集成与归一化例 同上 text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:499(搜「WasmEdge and Wasmer」) · text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:515(搜「normalize_sensor」)
SQLite 基准 同上 text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:525(搜「85-95% of native C」)
ScyllaDB 与内联计算 同上 text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:531(搜「close-to-the-metal」) · text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:561(搜「shard-per-core」)
三个插入点 同上 text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:661(搜「Integration Points」)
基准测试环境 同上 text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:743(搜「16-core AMD Ryzen」) · text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:763(搜「TPC-H」)
PostgreSQL 基准表 同上 text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:859(搜「180 ms」) · text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:895(搜「30–40%」)
ScyllaDB 基准表 同上 text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:965(搜「14 ms」) · text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:1001(搜「15–25%」)
三库对照总结表 同上 text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:1111(搜「Summary of WebAssembly Integration」)
四个生产用例 同上 text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:1123(搜「JSON Processing UDF」) · text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:1165(搜「Real-time Alerting」) · text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:1209(搜「Row-Level Access Filter」) · text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:1245(搜「Regex Search」)
部署七条 同上 text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:1349(搜「Pre-Compile Wasm Modules」) · text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:1519(搜「Feature Flags」) · text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:1609(搜「Versioning and Lifecycle」)
未来方向与生态表 同上 text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:1695(搜「Future Trends」) · text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:1927(搜「Extism」)

  1. 出处:「WebAssembly in Databases」第 71–101 段(text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:75,搜「high performance, scalability, and extensibility」)。 ↩

  2. 出处:「WebAssembly in Databases」第 157–175 段(text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:161,搜「Platform-specific」)。 ↩

  3. 出处:「WebAssembly in Databases」第 243–341 段(text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:339,搜「CI/CD pipelines for database logic」)。 ↩

  4. 出处:「WebAssembly in Databases」第 417–429 段(text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:421,搜「pg-wasm extension」)。 ↩

  5. 出处:「WebAssembly in Databases」第 431–461 段(text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:439,搜「rust_add」)与 text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:461(搜「Returns 8」)。 ↩

  6. 出处:「WebAssembly in Databases」第 463–483 段(text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:465,搜「20-30% better latency」)与 text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:895(搜「10-20% higher latency」)、text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:899(搜「10–20 MB」)。 ↩

  7. 出处:「WebAssembly in Databases」第 485–507 段(text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:499,搜「WasmEdge and Wasmer」)。 ↩

  8. 出处:「WebAssembly in Databases」第 509–521 段(text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:515,搜「normalize_sensor」)。 ↩

  9. 出处:「WebAssembly in Databases」第 523–525 段(text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:525,搜「85-95% of native C performance」)。 ↩

  10. 出处:「WebAssembly in Databases」第 527–569 段(text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:563,搜「external processing engine」)。 ↩

  11. 出处:「WebAssembly in Databases」第 661–687 段(text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:665,搜「Ingestion Layer」)。 ↩

  12. 出处:「WebAssembly in Databases」第 603–619 段(text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:605,搜「Custom filters」)。 ↩

  13. 出处:「WebAssembly in Databases」第 735–839 段(text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:743,搜「16-core AMD Ryzen」)与 text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:839(搜「five runs」)。 ↩

  14. 出处:「WebAssembly in Databases」第 841–901 段(text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:859,搜「180 ms」)与 text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:895(搜「30–40%」)。 ↩

  15. 出处:「WebAssembly in Databases」第 949–1009 段(text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:965,搜「14 ms」)与 text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:1001(搜「15–25%」)。 ↩

  16. 出处:「WebAssembly in Databases」第 1165–1207 段(text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:1199(搜「payload.temperature > 80.0」)与 text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:1191(搜「seconds to milliseconds」)。 ↩

  17. 出处:「WebAssembly in Databases」第 1123–1281 段(text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:1147(搜「30–50%」)与 text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:1267(搜「40–60% faster」)。 ↩

  18. 出处:「WebAssembly in Databases」第 1339–1693 段(text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:1349(搜「Pre-Compile Wasm Modules」)与 text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:1537(搜「Canary deployments」)、text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:1625(搜「Module hash」)。 ↩

  19. 出处:「WebAssembly in Databases」第 469–483 段(text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:481(搜「pg_stat_statements」)与 text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:475(搜「resource-constrained」)。 ↩

  20. 出处:「WebAssembly in Databases」第 497–521 段(text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:499(搜「WasmEdge and Wasmer」)与 text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:515(搜「normalize_sensor」)。 ↩

  21. 出处:「WebAssembly in Databases」第 603–619 段(text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:605(搜「Custom filters」);告警条件见 text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:1199(搜「payload.temperature > 80.0」)。 ↩

  22. 出处:「WebAssembly in Databases」第 1727–1899 段(text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:1731(搜「in-memory database engines」)与 text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:1859(搜「predict_churn」)、text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:1883(搜「wasm_compute」)。 ↩

  23. 出处:「WebAssembly in Databases」第 711–725 段(text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:715(搜「native UDF (User Defined Function) framework」)。 ↩