Snowflake开源pg_lake, 3天揽上千Star
Snowflake开源pg_lake, 3天揽上千Star
每次就是上一篇大新闻 | Snowflake 和 Databricks 为夺 PG 再次大打出手!说的主角,来了。
CrunchyData 被 Snowflake 收购后, 感觉更开放, 更给力了!
开源pg_lake系列插件, 让PG更顺畅的拥有数据湖的能力! 3天揽得1K Star.
https://github.com/Snowflake-Labs/pg_lake
pg_lake 是什么? 用于 Iceberg 和数据湖的 Postgres
pg_lake 将 Iceberg 和数据湖文件(data lake files)集成到 Postgres 中。通过 pg_lake扩展(extensions),您可以将 Postgres 用作一个独立的湖仓系统(lakehouse system),该系统支持对 Iceberg 表(Iceberg tables)执行事务(transactions)和快速查询(queries),并且可以直接处理 S3 等对象存储(object stores)中的原始数据文件(raw data files)。
pg_lake 的核心能力(At a high level)
在较高层面,pg_lake 允许您:
直接通过 PostgreSQL创建(Create)和修改(modify) Iceberg 表,具有完整的事务保证(transactional guarantees),并可从其他引擎(engines)进行查询(query)。 查询(Query)和导入(import) 对象存储(object storage)中的 Parquet、CSV、JSON 和 Iceberg 格式的数据文件(data files)。 使用 COPY 命令将查询结果(query results)以 Parquet、CSV 或 JSON 格式导出(Export)回对象存储。 读取 GDAL 支持的地理空间格式(geospatial formats),例如 GeoJSON 和 Shapefiles。 使用内置的 map 类型(map type)处理半结构化(semi-structured)或键值(key–value)数据。 在相同的 SQL 查询(SQL queries)和修改(modifications)中结合堆表(heap)、Iceberg 和外部 Parquet/CSV/JSON 文件——所有操作都具有完整的事务保证,且无 SQL 限制(SQL limitations)。 从 Iceberg、Parquet、JSON 和 CSV 文件等外部数据源(external data sources)中推断(Infer) 表列(table columns)和类型(types)。 利用(Leverage)底层的 DuckDB 查询引擎(query engine)进行快速执行(fast execution),而无需离开 Postgres。
来看看pg_lake的架构:
架构(Architecture)
一个 pg_lake实例(instance)由两个主要组件(components)组成:带有 pg_lake 扩展的 PostgreSQL 和 pgduck_server。用户连接到 PostgreSQL 运行 SQL 查询,而 pg_lake扩展通过与 Postgres 的钩子(hooks)集成,来处理查询规划(query planning)、事务边界(transaction boundaries)以及执行(execution)的整体编排(orchestration)。
在幕后(Behind the scenes),查询执行的部分被委托给 DuckDB。这是通过 pgduck_server 实现的,pgduck_server 是一个独立的多线程进程(multi-threaded process),它(在本地)实现了 PostgreSQL wire protocol 协议。
这个进程(process)运行 DuckDB,并结合我们的 duckdb_pglake扩展,该扩展添加了 PostgreSQL 兼容的函数(functions)和行为(behavior)。通常,用户不需要知道 pgduck_server 的存在;它透明地(transparently)运行以提高性能(performance)。在适当的时候,pg_lake 将数据扫描(scanning of the data)和计算(computation)委托给 DuckDB 的高度并行(highly parallel)、列式(column-oriented) 执行引擎。
这种分离(separation)也避免了将 DuckDB 直接嵌入(embedding)到 Postgres 进程(process)中可能产生的线程(threading)和内存安全限制(memory-safety limitations),因为 Postgres 进程是围绕进程隔离(process isolation)而非多线程执行设计的。
组件(Components)
pg_lake 遵循模块化设计(modular design),围绕一组可互操作的组件(set of interoperating components)构建。这些组件主要实现为 PostgreSQL 扩展,其他则为支持服务(supporting services)或库(libraries)。
当前的组件集(set of components)包括:
pg_lake_iceberg:一个实现了 Iceberg 规范 的 PostgreSQL 扩展。 pg_lake_table:一个实现了外部数据包装器(foreign data wrapper),用于查询对象存储中的文件的 PostgreSQL 扩展。 pg_lake_copy:一个实现了 COPY to/from 您的数据湖(data lake)的 PostgreSQL 扩展。 pg_lake_engine:用于不同 pg_lake扩展的通用模块(common module)。pg_extension_base:其他扩展的基础构建块(foundational building block)。 pg_extension_updater:用于在启动时更新所有扩展的扩展。 pg_lake_benchmark:对湖表(lake tables)执行各种基准测试(benchmarks)的 PostgreSQL 扩展。 pg_map:一个通用 map 类型生成器(generic map type generator)。 pgduck_server:一个独立服务器(stand-alone server),它将 DuckDB加载(loads)到同一服务器机器(server machine)上,并通过 PostgreSQL 协议暴露 (exposes) DuckDB 。 duckdb_pglake:一个 DuckDB 扩展,它向 DuckDB 添加了缺失的 PostgreSQL 函数 。
准备 pg_lake(Setting up pg_lake)
准备 pg_lake 有两种方式:使用 Docker(用于易于运行的测试环境)或从源代码构建(Building from source)(用于手动设置或开发用途)。这两种方法都包括 PostgreSQL 扩展(extensions)、pgduck_server应用(application)以及设置 S3 兼容存储(S3-compatible storage)。
使用 Docker
遵循 Docker README 以使用 Docker 设置和运行 pg_lake。
从源代码构建(Building from source)
一旦您 构建并安装了所需的组件 ,您就可以在 Postgres 内部 初始化 (initialize)pg_lake。
创建扩展(Creating the extensions)
使用 CASCADE 一次性创建所有必需的扩展:
CREATE EXTENSION pg_lake CASCADE;
NOTICE: installing required extension "pg_lake_table"
NOTICE: installing required extension "pg_lake_engine"
NOTICE: installing required extension "pg_extension_base"
NOTICE: installing required extension "pg_lake_iceberg"
NOTICE: installing required extension "pg_lake_copy"
CREATE EXTENSION
运行 pgduck_server(Running pgduck_server)
pgduck_server 是一个独立进程(standalone process),它(在本地)实现了 Postgres 的协议(wire-protocol),并在底层使用 DuckDB 来执行查询。
当您运行 pgduck_server 时,它会开始监听 Unix 域套接字(unix domain socket)上的端口 5332:
pgduck_server
LOG pgduck_server is listening on unix_socket_directory: /tmp with port 5332, max_clients allowed 10000
由于 pgduck_server 实现了 Postgres 线协议,您可以通过 psql 在端口 5332 和主机 /tmp 上访问它,并通过 DuckDB 运行命令。
例如,您可以获取 DuckDB 版本(DuckDB version):
psql -p 5332 -h /tmp
selectversion() as duckdb_version;
duckdb_version
----------------
v1.3.2 (1 row)
您也可以在启动服务器(server)时提供一些额外的设置(settings),要查看全部设置:
pgduck_server --help
在生产系统(production systems)上,有一些重要的设置应该被调整:
--memory_limit:可选地指定pgduck_server的最大内存(maximum memory),类似于 DuckDB 的memory_limit,默认是系统内存(system memory)的 80%。--init_file_path <path>:在启动(start-up)时执行此文件中的所有语句(statements)。--cache_dir:指定用于缓存(cache) 远程文件(remote files)(来自 S3)的目录(directory)。
将 pg_lake 连接到 S3(或兼容服务)
pgduck_server 依赖 DuckDB [secrets manager] 进行凭证(credentials)管理,它默认遵循 AWS 和 GCP 的凭证链(credentials chain)。请确保您的云凭证(cloud credentials)配置正确,例如,通过在 ~/.aws/credentials 中设置它们。
一旦您设置了凭证链,您应该设置 pg_lake_iceberg.default_location_prefix。这是 Iceberg 表的存储位置(location)。
SET pg_lake_iceberg.default_location_prefix TO's3://testbucketpglake';
您也可以在 pgduck_server 上设置凭证,用于 [使用 minio 进行本地开发] 。
使用 pg_lake(Using pg_lake)
创建 Iceberg 表(Create an Iceberg table)
您可以通过在 CREATE TABLE 语句中添加 USING iceberg 来创建 Iceberg 表。
CREATETABLE iceberg_test USING iceberg
ASSELECT
i askey, 'val_'|| i as val
FROM
generate_series(0,99)i;
然后,查询它:
SELECTcount(*) FROM iceberg_test;
count
-------
100
(1 row)
然后您可以看到 Iceberg 元数据位置(metadata location):
SELECT table_name, metadata_location FROM iceberg_tables;
table_name | metadata_location
-------------------+--------------------------------------------------------------------------------------------------------------------
iceberg_test | s3://testbucketpglake/postgres/public/test/435029/metadata/00001-f0c6e20a-fd1c-4645-87c9-c0c64b92992b.metadata.json
COPY 导入/导出 S3(COPY to/from S3)
您可以使用 COPY 命令直接导入(import)或导出(export) Parquet、CSV 或换行符分隔的 JSON(newline-delimited JSON)格式的数据。格式会从文件扩展名(file extension)中自动推断(inferred),或者您可以使用 COPY 选项(options)如 WITH (format 'csv', compression 'gzip') 来显式指定(specify it explicitly)。
-- 将数据从 Postgres 以 Parquet 格式复制到 S3
-- 从任何数据源读取,包括 iceberg 表、堆表或任何查询结果
COPY (SELECT * FROM iceberg_test) TO's3://testbucketpglake/parquet_data/iceberg_test.parquet';
-- 从 S3 复制回 Postgres 中的任何表
-- 此示例复制到 iceberg 表中,但也可以是堆表 (heap table)
COPY iceberg_test FROM 's3://testbucketpglake/parquet_data/iceberg_test.parquet';
为 S3 上的文件创建外部表(Create foreign table for files on s3)
您可以直接从一个文件或一组文件中创建外部表(foreign table),而无需指定列名(column names)或类型(types)。
-- 使用该路径下的文件,可以使用 * 代表所有文件
CREATEFOREIGNTABLE parquet_table()
SERVER pg_lake
OPTIONS (path's3://testbucketpglake/parquet_data/*.parquet');
-- 注意,我们从文件中推断列
\d parquet_table
Foreign table "public.parquet_table"
Column | Type | Collation | Nullable | Default | FDW options
--------+---------+-----------+----------+---------+-------------
key | integer | | | |
val | text | | | |
Server: pg_lake
FDW options: (path 's3://testbucketpglake/parquet_data/*.parquet')
-- 然后,查询它
select count(*) from parquet_table;
count
-------
100
(1 row)
历史(History)
pg_lake开发(development)始于 2024 年初的 Crunchy Data,目标是将 Iceberg 引入 PostgreSQL。最初的几个月专注于构建外部查询引擎(external query engine)(即 DuckDB)的稳健集成(integration)。为了尽早推向市场,查询/导入/导出(query/import/export)功能以 [Crunchy Bridge for Analytics] 的名称提供给 [Crunchy Bridge] 客户。
接下来,我们开始构建 Iceberg (v2) 协议的全面实现(comprehensive implementation),支持事务(transactions)和几乎所有 PostgreSQL 特性(features)。2024 年 11 月,我们将 Crunchy Bridge for Analytics 重新发布为 Crunchy Data Warehouse,可在 Crunchy Bridge 和本地(on-premises)使用。
2025 年 6 月,**[Crunchy Data 被 Snowflake 收购]。在收购(acquisition)之后,Snowflake** 决定在 2025 年 11 月将该项目开源(open source)为 pg_lake。初始版本(initial version)是 3.0,因为它之前已经有两代产品。