示例
读取单个 Parquet 文件
SELECT * FROM 'test.parquet';
确定 Parquet 文件中包含哪些列/类型
DESCRIBE SELECT * FROM 'test.parquet';
从 Parquet 文件创建表
CREATE TABLE test AS
SELECT * FROM 'test.parquet';
如果文件扩展名不是 .parquet,请使用 read_parquet 函数
SELECT *
FROM read_parquet('test.parq');
使用列表参数读取三个 Parquet 文件并将它们视为单个表
SELECT *
FROM read_parquet(['file1.parquet', 'file2.parquet', 'file3.parquet']);
读取所有匹配 glob 模式的文件
SELECT *
FROM 'test/*.parquet';
读取所有匹配 glob 模式的文件,并包含 filename 虚拟列,该列指定了每一行来自哪个文件(自 DuckDB v1.3.0 起,无需配置选项即可默认使用此列)
SELECT *, filename
FROM read_parquet('test/*.parquet');
使用 glob 列表读取两个特定文件夹中的所有 Parquet 文件
SELECT *
FROM read_parquet(['folder1/*.parquet', 'folder2/*.parquet']);
通过 HTTPS 读取
SELECT *
FROM read_parquet('https://some.url/some_file.parquet');
SELECT *
FROM parquet_metadata('test.parquet');
SELECT *
FROM parquet_file_metadata('test.parquet');
SELECT *
FROM parquet_kv_metadata('test.parquet');
SELECT *
FROM parquet_schema('test.parquet');
使用默认压缩方式 (Snappy) 将查询结果写入 Parquet 文件
COPY
(SELECT * FROM tbl)
TO 'result-snappy.parquet'
(FORMAT parquet);
使用指定的压缩方式和行组大小将查询结果写入 Parquet 文件
COPY
(FROM generate_series(100_000))
TO 'test.parquet'
(FORMAT parquet, COMPRESSION zstd, ROW_GROUP_SIZE 100_000);
将整个数据库的表内容导出为 Parquet
EXPORT DATABASE 'target_directory' (FORMAT parquet);
Parquet 文件
Parquet 文件是经过压缩的列式存储文件,加载和处理效率高。DuckDB 提供高效读取和写入 Parquet 文件的支持,并支持将过滤器和投影下推到 Parquet 文件扫描中。
Parquet 数据集因文件数量、单个文件大小、使用的压缩算法、行组大小等而异。这些因素对性能有显著影响。详情请参考性能指南。
read_parquet 函数
| 函数 | 描述 | 示例 |
|---|---|---|
read_parquet(path_or_list_of_paths) |
读取 Parquet 文件 | SELECT * FROM read_parquet('test.parquet'); |
parquet_scan(path_or_list_of_paths) |
read_parquet 的别名 |
SELECT * FROM parquet_scan('test.parquet'); |
如果文件以 .parquet 结尾,则函数语法是可选的。系统会自动推断您正在读取 Parquet 文件
SELECT * FROM 'test.parquet';
可以通过提供 glob 或文件列表一次读取多个文件。有关更多信息,请参阅多文件部分。
参数
有许多选项可传递给 read_parquet 函数或 COPY 语句。
| 名称 | 描述 | 类型 | 默认值 |
|---|---|---|---|
binary_as_string |
由旧版写入器生成的 Parquet 文件可能未正确设置字符串的 UTF8 标志,导致字符串列被加载为 BLOB。将其设置为 true 可将二进制列作为字符串加载。 |
BOOL |
false |
encryption_config |
Parquet 加密配置。 | STRUCT |
- |
文件名 |
结果中是否应包含额外的 filename 列。自 DuckDB v1.3.0 起,filename 列会自动作为虚拟列添加,保留此选项仅出于兼容性原因。 |
BOOL |
false |
file_row_number |
是否包含 file_row_number 列。 |
BOOL |
false |
hive_partitioning |
是否将路径解析为 Hive 分区路径。 | BOOL |
(自动检测) |
union_by_name |
多个架构的列是否应按名称统一,而不是按位置统一。 | BOOL |
false |
schema |
允许您以提供的架构读取 Parquet 文件。需要字段 ID。 | MAP |
NULL |
使用 schema 参数
schema 参数允许您使用特定架构读取 Parquet 文件。这对于读取 Parquet 文件时重命名、添加、删除、重新排序或转换列类型非常有用。
使用 DuckDB 创建 Parquet 时需要字段 ID。
示例
COPY (SELECT 42::INTEGER i) TO 'integers.parquet' (FIELD_IDS {i: 0});
读取 Parquet 文件
SELECT *
FROM read_parquet('integers.parquet', schema = MAP {
0: {name: 'renamed_i', type: 'BIGINT', default_value: NULL},
1: {name: 'new_column', type: 'UTINYINT', default_value: 43}
});
┌───────────┬────────────┐
│ renamed_i │ new_column │
│ int64 │ uint8 │
├───────────┼────────────┤
│ 42 │ 43 │
└───────────┴────────────┘
注意:此参数不能与 union_by_name=true 组合使用。
部分读取
DuckDB 支持将投影下推到 Parquet 文件本身。也就是说,在查询 Parquet 文件时,仅读取查询所需的列。这使您可以仅读取 Parquet 文件中感兴趣的部分。DuckDB 会自动完成此操作。
DuckDB 还支持将过滤器下推到 Parquet 读取器中。当您对从 Parquet 文件扫描的列应用过滤器时,该过滤器将被下推到扫描过程中,甚至可以使用内置的区域映射 (zonemaps) 跳过文件的部分内容。请注意,这取决于您的 Parquet 文件是否包含区域映射。
过滤器和投影下推提供了显著的性能优势。更多信息,请参阅我们的博文“使用 DuckDB 精确查询 Parquet”。
插入和视图
您还可以将数据插入表中,或直接从 Parquet 文件创建表。这将从 Parquet 文件加载数据并将其插入数据库。
将 Parquet 文件中的数据插入表中
INSERT INTO people
SELECT * FROM read_parquet('test.parquet');
直接从 Parquet 文件创建表
CREATE TABLE people AS
SELECT * FROM read_parquet('test.parquet');
如果您希望将数据保留在 Parquet 文件中,但想直接查询该文件,则可以在 read_parquet 函数上创建一个视图。然后,您可以像查询内置表一样查询 Parquet 文件。
在 Parquet 文件上创建视图
CREATE VIEW people AS
SELECT * FROM read_parquet('test.parquet');
查询 Parquet 文件
SELECT * FROM people;
写入 Parquet 文件
DuckDB 还支持使用 COPY 语句语法写入 Parquet 文件。有关详细信息(包括 COPY 语句的所有可能参数),请参阅 COPY 语句页面。
将查询写入 Snappy 压缩的 Parquet 文件
COPY
(SELECT * FROM tbl)
TO 'result-snappy.parquet'
(FORMAT parquet);
将 tbl 写入 zstd 压缩的 Parquet 文件
COPY tbl
TO 'result-zstd.parquet'
(FORMAT parquet, COMPRESSION zstd);
以最低压缩级别(获得最快压缩速度)将 tbl 写入 zstd 压缩的 Parquet 文件
COPY tbl
TO 'result-zstd.parquet'
(FORMAT parquet, COMPRESSION zstd, COMPRESSION_LEVEL 1);
使用键值元数据写入 Parquet 文件
COPY (
SELECT
42 AS number,
true AS is_even
) TO 'kv_metadata.parquet' (
FORMAT parquet,
KV_METADATA {
number: 'Answer to life, universe, and everything',
is_even: 'not ''odd''' -- single quotes in values must be escaped
}
);
将 CSV 文件写入未压缩的 Parquet 文件
COPY
'test.csv'
TO 'result-uncompressed.parquet'
(FORMAT parquet, COMPRESSION uncompressed);
将查询写入带有 zstd 压缩和行组大小的 Parquet 文件
COPY
(FROM generate_series(100_000))
TO 'row-groups-zstd.parquet'
(FORMAT parquet, COMPRESSION zstd, ROW_GROUP_SIZE 100_000);
将数据写入 LZ4 压缩的 Parquet 文件
COPY
(FROM generate_series(100_000))
TO 'result-lz4.parquet'
(FORMAT parquet, COMPRESSION lz4);
或者,等效地
COPY
(FROM generate_series(100_000))
TO 'result-lz4.parquet'
(FORMAT parquet, COMPRESSION lz4_raw);
将数据写入 Brotli 压缩的 Parquet 文件
COPY
(FROM generate_series(100_000))
TO 'result-brotli.parquet'
(FORMAT parquet, COMPRESSION brotli);
要配置 Parquet 文件字典页的页面大小,请使用 STRING_DICTIONARY_PAGE_SIZE_LIMIT 选项(默认值:1 MB)
COPY
lineitem
TO 'lineitem-with-custom-dictionary-size.parquet'
(FORMAT parquet, STRING_DICTIONARY_PAGE_SIZE_LIMIT 100_000);
DuckDB 的 EXPORT 命令可用于将整个数据库导出为一系列 Parquet 文件。有关更多详细信息,请参阅“EXPORT 语句”页面
将整个数据库的表内容导出为 Parquet
EXPORT DATABASE 'target_directory' (FORMAT parquet);
加密
DuckDB 支持读取和写入加密的 Parquet 文件。
支持的功能
支持的 Parquet 功能列表可在 Parquet 文档的“实现状态”页面上找到。
安装和加载 Parquet 扩展
对 Parquet 文件的支持是通过扩展启用的。parquet 扩展几乎随所有客户端一起提供。但是,如果您的客户端未内置 parquet 扩展,则必须单独安装该扩展。
INSTALL parquet;