跳转到主要内容

这是本节的多页打印视图。 .

返回本页常规视图.

快速开始与安装指南

在 PostgreSQL 14–18 上通过 Pigsty 软件包或从源码编译安装 pg_mooncake (v0.3.0) 与 pg_duckdb (1.2.0),配置 postgresql.conf 并启用扩展。

本指南介绍如何在 PostgreSQL 14、15、16、17 与 18 上安装 pg_mooncake(v0.3.0)(内嵌 moonlink(v0.0.1) 与 duckdb_mooncake(v0.0.2))及其依赖的 pg_duckdb(v1.2.0)。

1. 使用 Pigsty 安装二进制软件包(推荐)

在主流 Linux 发行版(el8、el9、el10、d12、d13、u22、u24、u26 × x86_64 / aarch64)上,最快、最可靠的安装方式是使用由 PGSTY 维护的 pig 包管理器。完整的各平台直链下载表请参阅下载与可用性矩阵。

# 1. 使用中国大陆镜像安装 pig 命令行工具
curl -fsSL https://repo.pigsty.cc/pig | bash

# 2. 配置 PGDG + Pigsty PGSQL 软件仓库(启用中国大陆 CDN 镜像)
pig repo add pgsql -u -r china

# 3. 安装 pg_duckdb 与 pg_mooncake(或通过 -v 18 指定 PostgreSQL 大版本)
pig install pg_duckdb pg_mooncake
# 1. 安装 pig 命令行工具
curl -fsSL https://repo.pigsty.io/pig | bash

# 2. 配置 PGDG + Pigsty PGSQL 软件仓库
pig repo add pgsql -u

# 3. 安装 pg_duckdb 与 pg_mooncake
pig install pg_duckdb pg_mooncake
# Debian / Ubuntu (APT) —— 以 PostgreSQL 18 为例:
sudo apt-get update
sudo apt-get install -y postgresql-18-pg-duckdb postgresql-18-pg-mooncake

# RHEL / Rocky / AlmaLinux (DNF) —— 以 PostgreSQL 18 为例:
sudo dnf install -y pg_duckdb_18 pg_mooncake_18

2. 配置 postgresql.conf 并启用扩展

pg_mooncake 依赖 PostgreSQL 逻辑复制将行存表的增量变更实时同步至 Moonlink,并通过 pg_duckdb 加载本地打包的 mooncake.duckdb_extension。请在 postgresql.conf(或通过 ALTER SYSTEM)中配置以下参数:

# Moonlink 逻辑复制所需配置
wal_level = logical
max_replication_slots = 32
max_wal_senders = 32
max_worker_processes = 16

# 预加载 pg_duckdb 与 pg_mooncake 动态库
shared_preload_libraries = 'pg_duckdb,pg_mooncake'

# 允许 pg_duckdb 加载本地未签名的 mooncake.duckdb_extension 扩展
duckdb.allow_community_extensions = true
duckdb.allow_unsigned_extensions = true

# 可选:仅当 mooncake.duckdb_extension 不在默认的 $(pg_config --sharedir)/extension/pg_mooncake 路径下时指定
# mooncake.extension_repository = '/usr/pgsql-18/share/extension/pg_mooncake'

重启 PostgreSQL 服务(例如 sudo systemctl restart postgresql-18 或 pig pg restart),随后使用 psql 连接目标数据库并创建扩展:

-- CASCADE 会自动启用所依赖的 pg_duckdb (1.2.0) 扩展
CREATE EXTENSION IF NOT EXISTS pg_mooncake CASCADE;
pg_duckdb 1.2.0 版本守卫说明

在执行 CREATE EXTENSION pg_mooncake 时,扩展初始化 SQL 脚本会显式校验 pg_extension 中的 pg_duckdb 版本必须为 1.2.0。如果当前环境安装了不兼容的 pg_duckdb 版本(例如 1.1.x 或 1.3.x),安装将立即报错中止。请始终同步升级 pg_duckdb 与 pg_mooncake。

3. 从源码编译构建(v0.3.0)

如果你需要从源码构建 pg_mooncake 0.3.0、pg_duckdb 1.2.0、duckdb_mooncake v0.0.2 与 moonlink v0.0.1:

编译前置依赖

  • PostgreSQL 开发头文件:postgresql-server-dev-14 至 18(或 postgresql17-devel / postgresql18-devel)
  • C/C++ 构建工具链:cmake、ninja-build、g++ 或 clang、libssl-dev、libcurl4-openssl-dev、liblz4-dev、libzstd-dev、protobuf-compiler(protoc)
  • Rust 工具链:Rust 1.99.0+(stable)以及严格匹配版本的 cargo-pgrx 0.19.3:
    cargo install --locked cargo-pgrx --version 0.19.3

克隆仓库、校验版本锁并编译安装

# 1. 递归克隆 pg_mooncake 及其子模块(pg_duckdb、duckdb_mooncake、moonlink)
git clone --recurse-submodules https://github.com/pgsty/pg_mooncake.git
cd pg_mooncake
git fetch --tags --force moonlink
git fetch --tags --force duckdb_mooncake

# 2. 校验所有子模块提交哈希、标签及 cargo-pgrx 0.19.3 版本
make check-versions

# 3. 编译并安装 pg_duckdb 1.2.0(内嵌 DuckDB v2.0.0)
export PGRX_PG_CONFIG_PATH=/usr/pgsql-18/bin/pg_config
make pg_duckdb PG_CONFIG="$PGRX_PG_CONFIG_PATH" PG_VERSION=pg18 JOBS=$(nproc)

# 4. 编译并安装 pg_mooncake 0.3.0 + duckdb_mooncake v0.0.2 + moonlink v0.0.1
make install PG_CONFIG="$PGRX_PG_CONFIG_PATH" PG_VERSION=pg18 JOBS=$(nproc)

4. Docker 容器镜像(Obsolete)

警告

Obsolete(过时,待更新维护):PGSTY 尚未发布 pg_mooncake 0.3.0 的 Docker 与 Kubernetes 镜像。以下上游历史命令使用的是旧版 mooncakelabs/pg_mooncake 镜像(内置 PostgreSQL 17 与早期版本 pg_mooncake),仅供历史参考。

# 拉取并启动上游历史容器镜像
docker pull mooncakelabs/pg_mooncake
docker run --name mooncake-demo \
  -e POSTGRES_HOST_AUTH_METHOD=trust \
  -p 5432:5432 -d \
  mooncakelabs/pg_mooncake

# 使用 psql 连接容器内数据库
docker exec -it mooncake-demo psql -U postgres

下一步

亲手创建你的第一张 USING mooncake 列存镜像表,体验事务写入、更新、回滚与跨表关联查询。

了解关于主键 / 复制标识、分区表行为、TRUNCATE 以及受支持 DDL 变更的工程约束。

1 - Hello World 快速上手教程

手把手教程:创建 PostgreSQL 行存表,通过 mooncake.create_table 创建实时列存镜像表,并执行增删改、回滚与跨表关联分析查询。

本教程将带你体验 pg_mooncake 的核心操作流程:创建标准的 PostgreSQL 行存表,创建实时同步的列存镜像表(USING mooncake),执行事务级 INSERT、UPDATE、DELETE 与 ROLLBACK,以及在列存镜像表与常规行存表之间执行混合 JOIN 查询。

1. 启用扩展

连接目标 PostgreSQL 数据库,确保已启用 pg_mooncake(及依赖的 pg_duckdb):

CREATE EXTENSION IF NOT EXISTS pg_mooncake CASCADE;

2. 创建行存表与实时列存镜像表

首先创建一张标准的 PostgreSQL 行存表(user_activity)用于承载业务写入,随后调用 mooncake.create_table 创建它的实时列存镜像表(user_activity_columnstore):

-- 1. 创建标准的 PostgreSQL 行存(堆)表
CREATE TABLE user_activity (
    user_id BIGINT PRIMARY KEY,
    activity_type TEXT,
    activity_timestamp TIMESTAMP,
    duration INT
);

-- 2. 为 user_activity 创建实时列存镜像表
CALL mooncake.create_table('user_activity_columnstore', 'user_activity');

在后台,mooncake.create_table 会自动创建 user_activity_columnstore USING mooncake 表,为 user_activity 建立逻辑复制槽,并将表元数据注册到 moonlink 引擎中。

3. 执行插入、更新与删除操作

所有写操作(INSERT、UPDATE、DELETE)均针对原始行存表(user_activity)执行,而分析型 SELECT 查询则针对列存镜像表(user_activity_columnstore)执行:

-- 向行存表插入数据
INSERT INTO user_activity VALUES
    (1, 'login', '2024-01-01 08:00:00', 120),
    (2, 'page_view', '2024-01-01 08:05:00', 30),
    (3, 'logout', '2024-01-01 08:30:00', 60),
    (4, 'error', '2024-01-01 08:13:00', 60);

-- 在行存表上更新一行
UPDATE user_activity SET duration = 180 WHERE user_id = 1;

-- 从行存表中删除一行
DELETE FROM user_activity WHERE user_id = 2;

-- 查询列存镜像表(会自动等待最新 WAL LSN 同步完成)
SELECT * FROM user_activity_columnstore ORDER BY user_id;

查询输出:

 user_id | activity_type | activity_timestamp  | duration
---------+---------------+---------------------+----------
       1 | login         | 2024-01-01 08:00:00 |      180
       3 | logout        | 2024-01-01 08:30:00 |       60
       4 | error         | 2024-01-01 08:13:00 |       60
(3 rows)

4. 事务一致性与回滚验证

Moonlink 仅从逻辑复制流中摄取已提交的 PostgreSQL 事务;未提交或已回滚(ROLLBACK)的事务绝不会出现在列存镜像表中:

BEGIN;
INSERT INTO user_activity VALUES
    (5, 'login', '2024-01-02 10:00:00', 200),
    (6, 'login', '2024-01-02 10:30:00', 90);
ROLLBACK;

-- 已回滚的行(user_id 5 和 6)不会出现在查询结果中
SELECT * FROM user_activity_columnstore ORDER BY user_id;

5. 列存表与行存表混合关联(JOIN)

你可以在两张列存镜像表之间执行关联查询,也可以在单条 SQL 中将 USING mooncake 列存镜像表与常规 PostgreSQL 行存表直接 JOIN:

-- 两张列存表之间的关联查询
SELECT ua.user_id, ua.activity_type, ua.duration
FROM user_activity_columnstore ua
JOIN user_activity_columnstore ua2 ON ua.user_id = ua2.user_id;

-- 创建一张常规 PostgreSQL 行存表存储用户信息
CREATE TABLE users (
    user_id BIGINT PRIMARY KEY,
    username TEXT,
    tier TEXT
);

INSERT INTO users VALUES
    (1, 'alice', 'enterprise'),
    (3, 'bob', 'pro'),
    (4, 'charlie', 'free');

-- 直接关联 PostgreSQL 行存表与列存镜像表
SELECT u.username, u.tier, ua.activity_type, ua.duration
FROM users u
JOIN user_activity_columnstore ua ON u.user_id = ua.user_id
ORDER BY u.user_id;

6. 查看复制状态并生成 Iceberg 快照

通过 mooncake.list_tables() 查看当前的提交 LSN、刷盘 LSN 及 Iceberg 仓库目录,或调用 mooncake.create_snapshot 将内存 Arrow 写缓冲区强制刷盘并生成新的 Apache Iceberg v2 快照:

-- 查看复制 LSN 进度与 Iceberg 仓库路径
SELECT * FROM mooncake.list_tables();

-- 将内存 Arrow 缓冲刷写为新的 Apache Iceberg v2 快照
CALL mooncake.create_snapshot('user_activity_columnstore');

2 - 已知限制说明

pg_mooncake (v0.3.0) 的运行要求与当前已知限制,涵盖主键与复制标识、分区表、TRUNCATE、DDL 变更以及未实现接口说明。

在生产环境部署使用 pg_mooncake(v0.3.0)之前,请仔细阅读以下架构约束与当前已知限制。

1. 列存镜像表为只读副本

通过 CALL mooncake.create_table(dst, src) 创建的表采用 USING mooncake 表访问方法,本质上是只读列存镜像表:

  • 不能直接对 USING mooncake 列存表执行 INSERT、UPDATE、DELETE 或 COPY(PostgreSQL 将直接拒绝修改)。
  • 所有数据写入和修改必须针对源行存表(src)执行,变更会通过 moonlink 逻辑复制自动同步至列存镜像。

2. 主键与 REPLICA IDENTITY FULL 要求

为了通过 PostgreSQL 逻辑复制准确同步 UPDATE 与 DELETE 操作,源表必须在 WAL 日志中提供完整的旧行标识:

  • 包含主键(Primary Key)的源表:开箱即用,直接利用主键标识行。
  • 不包含主键的普通源表:CALL mooncake.create_table(dst, src) 会在启动复制前自动对源表执行 ALTER TABLE src REPLICA IDENTITY FULL。
  • 分区源表(v0.3.0 行为说明):
    • 在 pg_mooncake 0.3.0 中,对没有主键的分区表调用 mooncake.create_table 时,会自动为分区父表以及所有现有叶子子分区设置 REPLICA IDENTITY FULL(修复了早期版本中子分区 UPDATE 事件缺少完整旧元组导致复制工作进程 Panic 的缺陷)。
    • 重要提示:如果在 mooncake.create_table 创建镜像之后又新增了子分区(CREATE TABLE ... PARTITION OF ...),在向该新分区执行 UPDATE 或 DELETE 之前,必须手动执行 ALTER TABLE <new_partition> REPLICA IDENTITY FULL;。

3. TRUNCATE 行为说明

  • 普通堆表:对已建立镜像的普通堆表执行 TRUNCATE 不会同步清空列存镜像表。
  • 分区表(冷热分层归档模式):对分区源表的单个旧子分区执行 TRUNCATE 或 DROP TABLE 会被列存镜像表有意忽略。这一设计使你可以安全地从 PostgreSQL 行存中删除历史冷分区以释放本地磁盘,同时在列存镜像中完整保留全部历史数据。详见大表分区归档指南。

4. 表结构变更(ALTER TABLE)

目前仅以下针对源行存表的 ALTER TABLE 操作会自动同步至列存镜像表:

  • ALTER TABLE <src> ADD COLUMN <col> <type>(新增列)
  • ALTER TABLE <src> DROP COLUMN <col>(删除列)

其他 DDL 变更(例如修改列类型 ALTER COLUMN ... TYPE 或重命名列 RENAME COLUMN)不会自动同步;如需执行复杂表结构变更,建议删除并重建列存镜像表(DROP TABLE <dst>; CALL mooncake.create_table('<dst>', '<src>');)。

5. 不支持的数据类型

pg_mooncake 支持所有常见的 PostgreSQL 数值、文本、布尔、日期/时间、UUID、JSON/JSONB 及常见数组类型,但以下类型暂不支持或存在限制:

  • PostgreSQL 自定义枚举类型(ENUM)、复合类型与域类型(DOMAIN)
  • pg_duckdb 尚未映射的几何类型与网络地址类型
  • 超出 DuckDB DECIMAL(38, s) 精度上限的超高精度 NUMERIC 值

6. mooncake.load_files 显式报错说明(SQLSTATE 0A000)

在 pg_mooncake 0.3.0 中,调用 CALL mooncake.load_files(dst, files) 会显式返回 SQLSTATE 0A000(ERRCODE_FEATURE_NOT_SUPPORTED:"mooncake.load_files is not implemented by the bundled Moonlink version")。

  • 在早期上游版本中,内嵌 Moonlink 服务的 import_data 处理器是一个空实现(no-op),会在未导入任何数据的情况下静默返回成功。
  • 如需导入外部 Parquet 或 CSV 文件,请通过 COPY 或 INSERT INTO ... SELECT * FROM duckdb.read_parquet(...) 写入源行存表,或者参考在 Postgres 中查询外部数据湖直接就地查询外部文件。