TL;DR

  1. DuckDB 和 PostgreSQL 都是数据库系统,但编程模型差异很大。
  2. DuckDB 更自然地使用 C++ ownership、RAII、exception 和 inheritance。
  3. PostgreSQL 使用 MemoryContext、ereport/longjmp 和 NodeTag。

简短对比

维度DuckDBPostgreSQL
内存管理smart pointer + RAIIMemoryContext
error handlingtry/catchlongjmp
多态表达inheritancenode + tag

这不是谁先进、谁落后的问题。它们来自不同语言,也来自不同工程历史。

Ownership 和生命周期

在 DuckDB 里,logical operator、physical operator、expression、catalog entry 经常是 C++ class。子对象通常由 unique_ptr 持有。

这很适合树状结构:

父节点拥有子节点
父节点销毁
子节点跟着销毁

RAII 把这个思路扩展到内存之外。数据库系统里有 file handle、lock、buffer pin、temporary state、transaction-local object。RAII 让资源释放和对象生命周期绑定。

PostgreSQL 不一样。很多对象分配在 MemoryContext 里。生命周期由 reset/delete 整个 context 管理,而不是靠每个对象析构。

Error handling

DuckDB 使用 C++ exception。parser、binder、optimizer、executor 遇到错误时可以抛异常,上层捕获后转成用户可见错误。

PostgreSQL 使用 ereport 和 longjmp。这和 MemoryContext 配合很好,因为错误跳出后可以清理一整块内存区域。

C++ exception 和 RAII 配合自然,因为栈展开时对象会析构。但 exception 不能变成普通控制流。数据库 hot path 不应该用 exception 表达每行数据上的正常分支。

Runtime type

DuckDB 可以用 C++ inheritance 表达 expression、operator、function data。行为可以挂在对象上。

PostgreSQL 更常见的是 Node 加 NodeTag。运行时检查 tag,再 cast 到具体结构。

C++ inheritance 的局部类型结构更强,但 virtual call、对象布局和模块边界都要小心。

NodeTag 的布局直接,适合 C,但类型安全更多依赖约定。

边界

重点不是 DuckDB “更 C++”。重点是数据库系统选择的语言模型会塑造运行时模型。

DuckDB 关注对象 ownership 和析构。PostgreSQL 关注区域生命周期和显式 tag。两条路线都自洽。