湖模式列存表

更新时间:
复制为 MD 格式

湖模式列存表(Lake Mode Column Store Table)是 Lindorm 基于开源 Apache Iceberg 标准构建的分析型数据存储形态。数据以列式文件格式持久化于 Lindorm 实例底层文件系统,同一实例内的 OLAP 资源组与 ETL 资源组共享同一份湖模式数据,天然支持多引擎协同读写。

湖模式列存表兼容 Iceberg 开放协议,可与 Apache Spark、Apache Flink 等计算引擎互联互通,适合构建多引擎共享的湖仓一体架构。与仓模式列存表相比,湖模式列存表更侧重数据共享与生态兼容;仓模式列存表则具备更完整的 SQL 能力和更高的即席查询性能。

连接 OLAP 资源组后,通过以下语句切换至湖模式列存表数据源:

SET CATALOG lindorm_columnar;

湖模式列存表

适用场景

  • 原始日志、行为事件、埋点数据等不需要更新的明细流水分析

  • 多引擎共享的离线数仓事实表,数据由 Flink/Spark 批量写入,OLAP 资源组负责分析查询

  • 需要与 Apache Spark、Apache Flink 等外部计算引擎互联互通的湖仓一体场景

数据模型

湖模式列存表基于 Apache Iceberg 构建,通过 Iceberg 的快照机制(Snapshot)管理数据版本,读写相互隔离。数据按分区组织存储,查询时通过分区裁剪跳过无关分区,同一实例内的多个引擎(OLAP 资源组、ETL 资源组、Flink、Spark)直接共享同一份底层数据,无需数据搬迁或同步。

使用方法

-- 示例:用户访问日志表(按年月分区)
-- 分区列 year、month 置于列定义末尾
CREATE TABLE access_log (
    user_id     BIGINT               COMMENT "用户ID",
    path        VARCHAR(512)         COMMENT "请求路径",
    status_code INT                  COMMENT "HTTP状态码",
    latency_ms  INT                  COMMENT "响应时延(毫秒)",
    region      VARCHAR(32)          COMMENT "地区",
    year        STRING      NOT NULL COMMENT "年",
    month       STRING      NOT NULL COMMENT "月"
)
ENGINE = iceberg
PARTITION BY (year, month);

-- 插入单行
INSERT INTO access_log VALUES (1001, '/api/v1/query', 200, 32, 'east', '2024', '03');

-- 将查询结果写入表(可跨 Catalog)
INSERT INTO access_log (user_id, path, status_code, latency_ms, region, year, month)
SELECT user_id, path, status_code, latency_ms, region, year, month
FROM default_catalog.ods.raw_access_log
WHERE year = '2024' AND month = '03';

-- 查询(带分区裁剪)
SELECT * FROM access_log WHERE year = '2024' AND month = '03' LIMIT 100;

-- 聚合分析
SELECT month, COUNT(*) AS pv, COUNT(DISTINCT user_id) AS uv
FROM access_log
WHERE year = '2024'
GROUP BY month
ORDER BY month;

-- 跨 Catalog 联表查询(湖模式列存与仓模式列存表关联)
SELECT a.user_id, a.path, u.user_level
FROM lindorm_columnar.db01.access_log a
JOIN default_catalog.dw.user_profile u ON a.user_id = u.user_id
WHERE a.year = '2024' AND a.month = '03';

注意事项

  • 分区列须置于列定义末尾:分区列必须排在所有非分区列之后,否则建表报错。

  • 写入不去重:相同内容的数据多次写入会生成多条独立记录,不会自动去重。

  • 不支持 CREATE TABLE AS SELECT(CTAS):须先建表再 INSERT INTO ... SELECT

  • TIMESTAMP 类型不支持:时间字段请使用 DATETIME 或 DATE

  • 多引擎数据实时可见:外部引擎写入的数据对 OLAP 资源组实时可见,无需额外刷新。


数据分布

湖模式列存表通过 PARTITION BY 子句控制数据的物理分布。合理的分区设计可实现查询时的有效分区裁剪,大幅降低扫描范围。

Identity 分区

按列的原始值直接分区,适合低基数的离散维度列(如地区、年、月、状态等)。查询时 WHERE 条件包含分区列的等值过滤,引擎自动跳过不相关分区,显著减少 I/O。

-- 按年月分区
PARTITION BY (year, month)

-- 按地区分区
PARTITION BY (region)
注意 分区列的取值不应过于离散,否则会产生海量小分区,增加元数据压力。

数据类型

类型

说明

BOOLEAN

布尔值

INT

32 位整数

BIGINT

64 位整数

FLOAT

单精度浮点

DOUBLE

双精度浮点

DECIMAL(p, s)

精确小数,推荐金融/交易场景

DATE

日期,格式 YYYY-MM-DD

DATETIME

日期时间

STRING / VARCHAR(N)

变长字符串

BINARY

二进制数据

ARRAY<T>

同类型元素数组

MAP<K, V>

键值对映射

计算特性

SQL 分析算子

湖模式列存表支持标准 SQL 分析语法,全面覆盖 OLAP 场景下的分析计算需求。

投影与过滤

SELECT 支持对指定列进行投影,列名可设置别名(AS)、参与算术表达式或函数计算。WHERE 子句支持多条件组合谓词:

谓词类型

示例

等值过滤

status_code = 200

范围过滤

latency_ms BETWEEN 0 AND 1000view_date >= '2024-01-01'

集合过滤

region IN ('east', 'north')status_code NOT IN (404, 500)

模糊匹配

path LIKE '/api/%'

NULL 判断

user_id IS NULLpath IS NOT NULL

正则过滤

path REGEXP '^/api/v[0-9]+'

谓词在执行时尽可能下推至存储层,减少数据读取量。

连接查询(JOIN)

支持以下连接类型:

JOIN 类型

说明

INNER JOIN

返回两表的匹配行

LEFT OUTER JOIN

保留左表所有行,右表无匹配则填 NULL

RIGHT OUTER JOIN

保留右表所有行,左表无匹配则填 NULL

FULL OUTER JOIN

保留两表所有行

CROSS JOIN

笛卡尔积

LEFT SEMI JOIN

仅返回左表中在右表有匹配的行,不返回右表列

LEFT ANTI JOIN

仅返回左表中在右表无匹配的行

支持跨 Catalog 联表查询,将湖模式列存数据与仓模式列存表或宽表引擎数据关联分析:

-- 湖模式列存与仓模式列存表关联
SELECT a.user_id, a.path, u.user_level
FROM lindorm_columnar.db01.access_log a
INNER JOIN default_catalog.dw.user_profile u ON a.user_id = u.user_id
WHERE a.year = '2024' AND a.month = '03'
  AND u.user_level IN ('gold', 'platinum');

集合运算

运算符

说明

UNION ALL

合并多个查询结果,保留重复行,性能更优

UNION

合并多个查询结果并去重

INTERSECT

返回两个结果集的交集

EXCEPT / MINUS

返回在第一个结果集中但不在第二个中的行

分组聚合(GROUP BY)

支持标准聚合函数(COUNTSUMAVGMINMAXCOUNT DISTINCT)以及通过 HAVING 对聚合结果二次过滤。

支持以下扩展聚合语法,一次扫描完成多维度汇总:

-- GROUPING SETS:显式指定多组维度组合
SELECT region, month, COUNT(*) AS pv
FROM access_log
GROUP BY GROUPING SETS ((region, month), (region), ());

-- ROLLUP:层级汇总(从细粒度到总计)
SELECT region, month, COUNT(*) AS pv
FROM access_log
GROUP BY ROLLUP (region, month);

-- CUBE:对所有维度的全量组合汇总
SELECT region, month, COUNT(*) AS pv
FROM access_log
GROUP BY CUBE (region, month);

排序与分页

支持 ORDER BY 多列排序(ASC / DESC),配合 LIMIT 和 OFFSET 实现分页查询。

SELECT user_id, path, latency_ms
FROM access_log
WHERE year = '2024' AND month = '03'
ORDER BY latency_ms DESC, user_id ASC
LIMIT 20 OFFSET 40;

子查询

支持以下子查询形式,优化器自动将可转换的子查询改写为等价 JOIN 执行:

子查询类型

示例

标量子查询

WHERE latency_ms > (SELECT AVG(latency_ms) FROM access_log)

IN / NOT IN 子查询

WHERE user_id IN (SELECT user_id FROM vip_users)

EXISTS / NOT EXISTS 子查询

WHERE EXISTS (SELECT 1 FROM blacklist WHERE ...)

相关子查询

子查询引用外层查询的列,逐行计算

窗口函数(Window Function)

窗口函数在保留原始行的同时对数据分组计算,是 OLAP 分析的核心能力。通过 OVER (PARTITION BY ... ORDER BY ... ROWS/RANGE ...) 语法定义计算窗口。

函数类别

常用函数

排名函数

ROW_NUMBER()RANK()DENSE_RANK()NTILE(n)

聚合分析

SUM()AVG()MIN()MAX()(支持滑动窗口)

偏移访问

LAG(col, n, default)LEAD(col, n, default)

首尾取值

FIRST_VALUE(col)LAST_VALUE(col)

-- 计算每个用户的累计访问次数与当月访问排名
SELECT
    user_id,
    path,
    year,
    month,
    COUNT(*) OVER (
        PARTITION BY user_id
        ORDER BY month
        ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
    ) AS cumulative_pv,
    RANK() OVER (
        PARTITION BY month
        ORDER BY COUNT(*) DESC
    ) AS monthly_rank
FROM access_log;

-- 计算相邻两次请求的响应时延差
SELECT
    user_id,
    path,
    latency_ms,
    latency_ms - LAG(latency_ms, 1) OVER (PARTITION BY user_id ORDER BY year, month) AS latency_diff
FROM access_log;

CASE WHEN 条件表达式

支持搜索式和简单式两种语法,可在 SELECTWHEREORDER BY、聚合函数等任意位置使用。

SELECT
    user_id,
    path,
    latency_ms,
    CASE
        WHEN latency_ms < 100  THEN '快速'
        WHEN latency_ms < 500  THEN '正常'
        WHEN latency_ms < 2000 THEN '较慢'
        ELSE '超时'
    END AS latency_tier,
    SUM(CASE WHEN status_code = 200 THEN 1 ELSE 0 END) AS success_cnt
FROM access_log
GROUP BY user_id, path, latency_ms;

元数据访问

湖模式列存表基于 Iceberg 构建,每张表维护有完整的元数据,包括快照历史、分区状态、数据文件清单等。通过在表名后追加 $<元数据表名> 的方式可直接查询这些元数据,无需任何额外配置。

元数据表

说明

table$partitions

当前各分区的行数、文件数、数据量等统计信息

table$snapshots

表的所有快照列表,含快照ID、提交时间、操作类型

table$history

表的元数据变更历史

table$manifests

与各快照关联的 Manifest 文件概览

table$files

当前快照中所有数据文件的路径、格式、大小等详情

table$refs

表的引用信息,包括分支(Branch)和标签(Tag)

-- 查看表的分区统计
SELECT * FROM lindorm_columnar.db01.access_log$partitions;

-- 查看快照列表(可用于了解数据写入历史)
SELECT * FROM lindorm_columnar.db01.access_log$snapshots
ORDER BY committed_at DESC LIMIT 10;

-- 查看元数据变更历史
SELECT * FROM lindorm_columnar.db01.access_log$history;

-- 查看当前快照中的数据文件详情
SELECT * FROM lindorm_columnar.db01.access_log$files;