数据库里的 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
- Wasm 运行时(如 Wasmtime)嵌进 PostgreSQL 进程;
- 一座桥:SQL 类型 ↔ Wasm 函数的参数映射;
- 模块注册成 UDF,用 SQL 直接调。
书里的完整最小例子,Rust 写加法:5
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
基准: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 |
3.7 部署纪律七条¶
- AOT 预编译:模块一律提前编译优化(wasm-opt -O3),拒绝运行时动态编译;
- 轻量运行时:Wasmtime(生产标杆)/ WasmEdge(边缘);Lucet 标注为 legacy;
- 限额:内存上限(模块内
memory(1)或宿主 cap)、执行超时、Tokio 异步超时包裹; - 结构化日志:模块名/版本、时间戳、截断的出入参、异常、进出内存——ELK/Loki 集中, 打租户/分片标签;
- 特性开关:金丝雀发布(先放一小撮查询)、按租户灰度、定时自动回滚;
- 安全:WASI 能力审计到最小、非 root 运行、按租户隔离、wasm-objdump 定期扫二进制;
- 版本注册表:像容器镜像仓一样管模块——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. 可带走的¶
- 数据库扩展的三难:慢(脚本)、险(C 扩展)、绑定(平台)——Wasm 同时解三个,代价是 10–20MB 内存 + 10–20% 速度。
- 性能排序记死:PL/pgSQL < Wasm < 原生 C;嵌入式场景 Wasm 常是唯一选项。
- ScyllaDB 的账:内联聚合延迟 -15–25%、吞吐 100k→140k/秒、数据传输成本归零。
- 「数据库逻辑进 CI/CD」是范式级变化:版本化、灰度、回滚,存储过程也配。
- 三个插入点背下来:摄入层(写前)、查询层(读时)、代理层(中间)。
- 部署七条:AOT、轻量运行时、限额、结构化日志、特性开关、WASI 最小化、版本注册表。
- 基准数字都是「点估计」,移植排序不移植绝对值。
- 把「路线图」和「现货」分开读:本章不少能力标着 future directions。
- 内存上限 + 执行超时是多租户的生命线,不是可选项。
- 生态工具认八个名字: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」) |
-
出处:「WebAssembly in Databases」第 71–101 段(
text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:75,搜「high performance, scalability, and extensibility」)。 ↩ -
出处:「WebAssembly in Databases」第 157–175 段(
text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:161,搜「Platform-specific」)。 ↩ -
出处:「WebAssembly in Databases」第 243–341 段(
text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:339,搜「CI/CD pipelines for database logic」)。 ↩ -
出处:「WebAssembly in Databases」第 417–429 段(
text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:421,搜「pg-wasm extension」)。 ↩ -
出处:「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」)。 ↩ -
出处:「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」)。 ↩ -
出处:「WebAssembly in Databases」第 485–507 段(
text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:499,搜「WasmEdge and Wasmer」)。 ↩ -
出处:「WebAssembly in Databases」第 509–521 段(
text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:515,搜「normalize_sensor」)。 ↩ -
出处:「WebAssembly in Databases」第 523–525 段(
text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:525,搜「85-95% of native C performance」)。 ↩ -
出处:「WebAssembly in Databases」第 527–569 段(
text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:563,搜「external processing engine」)。 ↩ -
出处:「WebAssembly in Databases」第 661–687 段(
text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:665,搜「Ingestion Layer」)。 ↩ -
出处:「WebAssembly in Databases」第 603–619 段(
text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:605,搜「Custom filters」)。 ↩ -
出处:「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」)。 ↩ -
出处:「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%」)。 ↩ -
出处:「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%」)。 ↩ -
出处:「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」)。 ↩ -
出处:「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」)。 ↩ -
出处:「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」)。 ↩ -
出处:「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」)。 ↩ -
出处:「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」)。 ↩ -
出处:「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」)。 ↩ -
出处:「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」)。 ↩ -
出处:「WebAssembly in Databases」第 711–725 段(
text/22-fm-ultimate-webassembly-for-high-performance-apps-b.txt:715(搜「native UDF (User Defined Function) framework」)。 ↩