生成列
生成列
生成列(Generated Columns)是 Lakehouse 表中的一列,其值由表中的其他列通过表达式自动计算生成。创建时定义计算规则,系统根据规则自动维护列值,无需用户显式插入或更新。常见场景:数据集成同步时在数据库层统一完成字段转换,或将 JSON 字段提取为独立列并建立索引加速查询。
生成列支持两种存储模式:
| 模式 | 关键字 | 说明 |
|---|
| VIRTUAL(默认) | 省略或写 VIRTUAL
VIRTUAL | 不写入 Parquet 文件,查询时动态计算。无额外存储开销。 |
| STORED | STORED
STORED | 写入时物化到 Parquet 文件。查询直接读列,优化器可复用,支持 CLUSTER BY。 |
语法
CREATE TABLE [ IF NOT EXISTS ] table_name
(
column_definition,
-- VIRTUAL(默认):不写入文件,读时计算
col_name data_type GENERATED ALWAYS AS ( expr ) [VIRTUAL],
-- STORED:写入时物化
col_name data_type GENERATED ALWAYS AS ( expr ) STORED,
[column_definition, ...]
)
[ PARTITIONED BY (column_name column_type | column_name) ];
GENERATED ALWAYS AS (expr):通过表达式
expr
expr
自动生成列的值。表达式支持常量和内置标量确定性函数,不支持以下内容:
- 非确定性函数:
current_date()
current_date()
、current_timestamp()
current_timestamp()
、rand()
rand()
等
- 聚合函数:
sum()
sum()
、count()
count()
、avg()
avg()
等
- 窗口函数:
row_number()
row_number()
、rank()
rank()
等
- 子查询
- 自引用或循环依赖
支持将生成列作为分区列。
示例:
-- VIRTUAL 生成列(默认):不落盘,读时计算
CREATE TABLE t_virtual (
col1 TIMESTAMP,
hour_col INT GENERATED ALWAYS AS (hour(col1)),
pt STRING GENERATED ALWAYS AS (date_format(col1, 'yyyy-MM-dd'))
) PARTITIONED BY (pt);
-- STORED 生成列:物化写入,支持 CLUSTER BY
CREATE TABLE t_stored (
col1 INT,
col2 INT GENERATED ALWAYS AS (col1 + 1) STORED
) CLUSTERED BY (col2) SORTED BY (col2) INTO 8 BUCKETS;
-- JSON 提取 + 倒排索引(VIRTUAL 典型场景)
CREATE TABLE t_json (
id INT,
payload JSON,
level STRING GENERATED ALWAYS AS (json_extract_string(payload, '$.level')),
INDEX idx_level(level) USING INVERTED
) USING PARQUET;
生成列和默认值区别
| 对比项 | 默认值(DEFAULT) | 生成列(GENERATED ALWAYS AS) |
|---|
| 分区列支持 | 不支持 | 支持 |
| 非确定性函数 | 支持(如 current_timestamp()
current_timestamp() ) | 不支持 |
| 插入时能否指定值 | 可以指定,未指定则用默认值 | 不能指定,完全由表达式决定 |
| 列值来源 | 静态常量或非确定性函数 | 其他列的计算结果 |
| ALTER TABLE ADD 后存量行为 | 已有行该列填充为 NULL | VIRTUAL:读时按表达式计算,立即可见;STORED:已有行为 NULL(旧文件未物化) |
使用限制
- 插入时不能为生成列显式指定值,否则报错
insert.generated.column
insert.generated.column
。例外:分区字段指定静态值时不报错,但指定值不生效,查询结果仍由表达式决定(Hive 语法兼容)。
- 不支持实时接口和批量接口写入(含 Studio 数据集成的批量导入和实时写入)。
- VIRTUAL 生成列不能用于
CLUSTER BY
CLUSTER BY
/ SORTED BY
SORTED BY
,需改为 STORED 模式。
- Dynamic Table / 物化视图的列定义中不支持生成列。
DROP COLUMN
DROP COLUMN
时,若被删除列被其他生成列依赖,会报错 column.dependency
column.dependency
,需先删除依赖方列。
插入数据
插入时只提供基础列,生成列由系统自动维护:
-- ✅ 正确:只插入 col1,pt 由表达式自动计算
INSERT INTO t_virtual (col1) VALUES (TIMESTAMP '2024-09-26 10:00:00');
-- ❌ 错误:显式指定生成列值,报错 insert.generated.column
INSERT INTO t_virtual (col1, pt) VALUES (TIMESTAMP '2024-09-26 10:00:00', '2024-09-26');
添加字段时指定生成列
语法
ALTER TABLE table_name ADD COLUMN
column_name data_type GENERATED ALWAYS AS ( expr )
[FIRST | AFTER column_name]
[COMMENT column_comment];
说明:
示例
-- 添加 VIRTUAL 生成列(推荐,开箱即用)
ALTER TABLE my_table ADD COLUMN
year_col INT GENERATED ALWAYS AS (year(event_time))
AFTER event_time;
-- 添加后,已有行的 year_col 在查询时自动计算
SELECT id, event_time, year_col FROM my_table LIMIT 5;