PAX 存储格式
Apache Cloudberry 支 持 PAX (Partition Attributes Across) 存储格式。
PAX 是一种数据库存储格式,它结合了行式存储 (NSM,N-ary Storage Model) 和列式存储 (DSM,Decomposition Storage Model) 的优点,旨在提高数据库的查询性能,尤其是在缓存效率方面。在 OLAP 场景下,PAX 拥有媲美行式存储的批量写入性能和列式存储的读取性能。PAX 既能适应云环境下基于对象存储的存储模型,也能适应于线下传统基于物理文件的存储方式。
与传统存储格式相比,PAX 还有以下特性:
- 数据更新和删除:PAX 采用标记删除的方式对数据进行删除和更新,这样可以有效地管理存储在物理文件中的数据变更,而无需立即重写整个数据文件。
- 并发控制与读写隔离:PAX 使用多版本并发控制 (MVCC) 技术来实现高效的并发控制和读写隔离,其控制粒度达到单个数据文件级别,增强了操作的安全性和效率。
- 索引支持:支持 B-tree 索引,这有助于加速查询操作,特别是在处理大量数据时可以显著提高数据检索速度。
- 数据编码与压缩:PAX 提供多种数据编码(如 run-length encoding, delta encoding)和压缩方法(如 zstd, zlib),及多种压缩级别,这些特性帮助减少存储空间需求,同时优化读取性能。
- 统计信息:数据文件包含详细的统计信息,这些信息用于快速过滤和查询优化,从而减少不必要的数据扫描,加快查询处理速度。
适用场景
PAX 的混合存储能力使其适合于需要处理大量数据写入和频繁查询的复杂 OLAP 应用。无论是在云基础设施中寻求高性能数据分析解决方案,还是在传统数据中心环境中处理大规模数 据集,PAX 都能提供强大支持。
从源码编译 Cloudberry 时启用 PAX
要在从源码编译 Apache Cloudberry 时启用 PAX,你需要:
-
确保满足以下依赖要求:
- C/C++ 编译器:GCC/GCC-C++ 11 或更高版本
- CMake:3.11 或更高版本
- Protobuf:3.5.0 或更高版本
- ZSTD (libzstd):1.4.0 或更高版本
-
在 Cloudberry 源码目录的顶层运行以下命令以下载子模块:
git submodule update --init --recursive
执行该命令会下载这些子模块,用来构建和测试 PAX:
- yyjson (
dependency/yyjson
) - cpp-stub (
contrib/pax_storage/src/cpp/cotnrib
) - googlebench (
contrib/pax_storage/src/cpp/cotnrib
) - googletest (
contrib/pax_storage/src/cpp/cotnrib
) - tabulate (
contrib/pax_storage/src/cpp/cotnrib
)
注意上述子模块已经包含在最新发布的源代码压缩包中,因此解压后无需手动下载这些子模块。
- yyjson (
-
在运行
configure
命令时,添加--enable-pax
选项。例如:./configure --enable-pax --with-perl --with-python --with-libxml --with-gssapi --prefix=/usr/local/cloudberrydb
另外,如果要在
DEBUG
模式下启用 PAX,请在configure
命令中添加--enable-cassert
选项(与--enable-pax
一起),PAX 中的GTEST
将会被编译。运行GTEST
如下:cd contrib/pax_storage/build
./src/cpp/test_main
如果你对 PAX 的实现细节感兴趣,可以参考 GitHub 仓库中的设计文档。
使用方法
创建 PAX 的表
要创建 PAX 格式的表,你需要将表的访问方式 (Table Access Method) 设为 PAX,可以参照以下任一方法进行设置:
-
在建表时显式使用
USING PAX
子句,例如:CREATE TABLE t1(a int, b int, c text) USING PAX;
-- t1 为 PAX 表,可以作为普通 heap 表使用。 -
先设置表的默认访问方式,然后再建表:
-- 设置表的默认访问方式,此后新建的表都将使用 PAX 格式。
SET default_table_access_method = pax;
-- 隐式使用默认表访问方式,即 PAX。
CREATE TABLE t1(a int, b int, c text);
在建表时,你还可以指定部分列的最小值和最大值信息,以加速查询:
-- 通过 WITH(minmax_columns='b,c') 指定了对
-- 列 b 和 c 记录最小值和最大值(minmax)统计信息。
-- 这可以帮助优化那些涉及这两列的查询,
-- 因为系统可以快速判断哪些数据块可能包含符合条件的数据。
CREATE TABLE p2(a INT, b INT, c INT) USING pax WITH(minmax_columns='b,c');
INSERT INTO p2 SELECT i, i * 2, i * 3 FROM generate_series(1,10)i;
-- 由于 b 列有 minmax 统计信息,
-- 系统可以快速定位到可能包含该值的数据块,从而加速查询过程。
SELECT * FROM p2 WHERE b = 4;
-- 同样,由于 b 列的 minmax 信息,系统能迅速确定没有数据块能满足这个条件
--(如果所有生成的值都是正的),可能直接返回没有数据的结果,从而避免不必要的数据扫描。
SELECT * FROM p2 WHERE b < 0;
-- 修改表 p2 的 minmax 统计信息设置,使其仅适用于列 b。对于之后插入的数据,
-- 只有 b 列会维护这种统计信息,而对已存在的数据不会产生影响,也不会进行重新写入或调整。
ALTER TABLE p2 SET(minmax_columns='b');
查看已有表的格式
要查看一张表是否为 PAX 格式,可使用下面任一方法:
-
使用
psql
命令\d+
:gpadmin=# \d+ t1
Table "public.t1"
Column | Type | Collation | Nullable | Default | Storage | Compression | Stats target | Description
--------+---------+-----------+----------+---------+----------+-------------+--------------+-------------
a | integer | | | | plain | | |
b | integer | | | | plain | | |
c | text | | | | extended | | |
Distributed by: (a)
Access method: pax -
查询系统目录表
pg_class
和pg_am
:SELECT relname, amname FROM pg_class, pg_am WHERE relam = pg_am.oid AND relname = 't1';
relname | amname
---------+--------
t1 | pax
(1 row)