云原生DuckDB列存表需要在 PostgreSQL 和 DuckDB 之间完成建表映射、写入转换及查询结果转换。本文说明可用于建表和写入的类型、精度及数组限制,用于根据数据特征选择合适的列类型。未列出的类型即使偶尔能够建表,也不能视为受支持。
类型声明语法
CREATE TABLE table_name (
column_name data_type
[, ...]
) USING duckdb;参数
标量类型
类别 | PostgreSQL 类型 | DuckDB 物理类型或说明 |
布尔 |
|
|
整数 |
| 对应的有符号整数 |
对象标识 |
| 无符号 32 位整数 |
定点数 |
| 当 |
浮点数 |
|
|
货币 |
| DuckDB |
内部字符 | PostgreSQL 内部 | DuckDB |
字符串 |
| DuckDB |
二进制 |
|
|
位串 |
|
|
日期时间 |
| 对应的 DuckDB 日期时间类型 |
标识符 |
|
|
JSON |
|
|
XML |
|
|
扩展类型 |
| 安装对应类型扩展后映射为 |
二进制、位串、JSON 和 XML 的存取行为说明见BYTEA、BIT、JSON 和 XML章节,日期时间类型的时区与无穷值行为见日期、时间和时区章节。
示例
CREATE TABLE columnar_type_example (
id bigint,
amount numeric(18, 4),
ratio double precision,
enabled boolean,
label text,
payload jsonb,
raw bytea,
event_time timestamptz,
request_id uuid
) USING duckdb;NUMERIC 和 DECIMAL
语法
numeric [ ( precision [, scale ] ) ]
decimal [ ( precision [, scale ] ) ]参数
precision:有效数字总位数,DuckDBDECIMAL最大为 38scale:小数位数,负scale不受支持
没有声明精度的 numeric,以及精度大于 38 的声明,使用 polar_csi.decimal_default 指定的 DuckDB 类型,默认值为 DECIMAL(38,10)。
使用说明
建议优先声明精度和小数位数:
amount numeric(18, 2)numeric(p,s)在p <= 38且scale有效时映射为与声明一致的DECIMAL(p,s)。未声明精度的numeric默认只有 10 位小数,超过目标小数位数(即声明的scale或polar_csi.decimal_default指定的小数位数)的小数位会丢失,超出目标整数位范围的值会报转换错误。PostgreSQL
numeric的NaN、Infinity和-Infinity不能表示成 DuckDBDECIMAL,INSERT路径会把这些非有限值写成NULL,应避免向列存numeric列写入非有限值。浮点类型
real和double precision可以保存浮点NaN和无穷值,它们与numeric的行为不同。
数组类型
语法
element_type[]支持下列一维数组:
boolean[]smallint[]、integer[]、bigint[]、oid[]numeric[]、real[]、double precision[]character[]、varchar[]、text[]date[]、time[]、timetz[]、timestamp[]、timestamptz[]、interval[]uuid[]、bytea[]json[]、jsonb[]
示例:
数组可以为空,也可以包含 NULL 元素:
CREATE TABLE columnar_array_example (
id integer,
values integer[],
labels text[]
) USING duckdb;
INSERT INTO columnar_array_example VALUES
(1, ARRAY[1, NULL, 3], ARRAY['a', 'b']),
(2, ARRAY[]::integer[], NULL);数组维度和下界
DuckDB 列存数组只保存一维、下界为 1 的值。以下两种写入会报错。多行 INSERT 中任一行触发该类错误时,整条语句失败并回滚,已处理的行不会保留。
多维数组不受支持:
INSERT INTO columnar_array_example VALUES (3, ARRAY[[1, 2], [3, 4]], NULL);ERROR: multidimensional arrays are not supported on duckdb tables DETAIL: The array has 2 dimensions, but DuckDB storage only supports empty or one-dimensional arrays.下界不是 1 的数组不受支持:
INSERT INTO columnar_array_example VALUES (4, '[5:7]={10,20,30}'::integer[], NULL);ERROR: array lower bounds other than 1 are not supported on duckdb tables DETAIL: The array lower bound is 5, but DuckDB storage only supports lower bound 1.
PostgreSQL 内部单字节类型 "char"[] 明确不受支持。它与 SQL 定长字符数组 character[] 不是同一种类型。
numeric[]
未声明精度的 numeric[] 使用 polar_csi.decimal_default 指定的元素类型,默认映射为 DuckDB DECIMAL(38,10)[]。显式声明且精度不超过 38 的 numeric(p,s)[] 保留声明的精度和小数位数。精度大于 38 时使用 polar_csi.decimal_default。
默认
DECIMAL(38,10)[]映射下,每个元素最多有 38 位有效数字,其中 10 位为小数,超出范围时整条写入报转换错误。NaN、Infinity和-Infinity元素会写成NULL。
需要超过默认的 10 位小数、超过该范围,或不能接受非有限值变成 NULL 时,不应使用默认映射的 numeric[]。可以把数值拆成标量列、改用受控的整数缩放表示,或以文本保存后显式解析。
日期、时间和时区
timestamp保存无时区时间。timestamptz保存绝对时间,显示受会话TimeZone影响。UPDATE和DELETE中没有时区偏移的timestamptz常量,先按当前 PostgreSQL 会话时区解释,再传给 DuckDB。date、timestamp和timestamptz的正负无穷值有专门的转换路径。
示例
对跨时区交换的数据,建议显式设置会话时区,并把偏移写进字面量:
SET timezone = 'UTC';
INSERT INTO columnar_type_example (id, event_time)
VALUES (1, TIMESTAMPTZ '2026-08-26 08:00:00+00');字符串和排序规则
character(n) 的长度和尾部空格由 PostgreSQL 输入类型检查。DuckDB 的物理 VARCHAR 本身不保存长度。查询中的比较和排序由 DuckDB 执行,PostgreSQL 数据库的 libc 排序规则不会自动成为每个 DuckDB 表达式的排序规则。
对区域设置、大小写或非 ASCII 排序敏感的场景,应使用真实数据验证结果,并为 ORDER BY 显式指定 NULL 顺序。需要严格依赖 PostgreSQL 区域设置语义时,应使用行存表。
BYTEA、BIT、JSON 和 XML
bytea以 DuckDBBLOB保存,支持 PostgreSQL 输入函数接受的二进制值。bit和bit varying以 DuckDBBITSTRING保存。json和jsonb可以存取;jsonb写入时转换成 JSON 文本;JSON 函数只有在 DuckDB 存在兼容实现时才能用于列存查询。xml以VARCHAR文本形式存入 DuckDB,仍会经过 PostgreSQL XML 输入检查,读取时恢复成 PostgreSQL XML。
示例
INSERT INTO columnar_type_example (id, payload, raw)
VALUES (
2,
'{"event":"click","ok":true}'::jsonb,
'\x00ff'::bytea
);不支持的类型
不支持下列类型类别:
Domain 和 Enum
复合类型和
record列range和multirange几何、网络、全文检索以及其他没有列存转换器的内置类型
未注册列存写入和读取转换的扩展类型。
修改列类型
语法
ALTER TABLE table_name
ALTER COLUMN column_name TYPE data_type;DuckDB 必须能把所有已有值转换成新类型,且语句不能使用 USING。
示例
ALTER TABLE columnar_type_example
ALTER COLUMN id TYPE numeric(20, 0);不确定转换是否兼容时,应使用CREATE TABLE AS SELECT创建新列存表并显式转换数据。列存表不支持以另一张列存表作为 INSERT ... SELECT 的数据来源,复制列存表数据请使用CREATE TABLE AS SELECT:
CREATE TABLE columnar_type_example_new
USING duckdb AS
SELECT id::numeric(20, 0), amount::numeric(20, 4)
FROM columnar_type_example;应用于生产环境
不要把 CREATE TABLE 成功作为类型受支持的依据。生产表至少应验证 NULL、边界值、批量 INSERT、SELECT、UPDATE、COPY 以及备份恢复。