如何高效从ClickHouse的Array(Nested)列提取数据?
问题描述
需要将ClickHouse表中Array(Nested)类型的列数据展开为指定格式,同时缩短查询时间。
建表语句
CREATE TABLE default.ntest2( job_name String, list_data Array(Nested(s UInt64, e UInt64, name String)) ) ENGINE = MergeTree ORDER BY (job_name) SETTINGS index_granularity = 8192;
表数据
| job_name | list_data |
|---|---|
| job1 | [[(1,2,'name1')],[(4,5,'name2')]] |
| job2 | [[(22,33,'name3')],[(44,55,'name4')]] |
期望输出
| job_name | list_data.s | list_data.e | list_data.name |
|---|---|---|---|
| job1 | 1 | 2 | 'name1' |
| job1 | 4 | 5 | 'name2' |
| job2 | 22 | 33 | 'name3' |
| job2 | 44 | 55 | 'name4' |
高效实现方案
1. 基础高效查询语句
使用ClickHouse原生的ARRAY JOIN操作展开嵌套数组,该操作针对列式存储做了深度优化,性能表现优异:
SELECT job_name, item.s AS `list_data.s`, item.e AS `list_data.e`, item.name AS `list_data.name` FROM default.ntest2 ARRAY JOIN list_data AS item
2. 缩短查询时间的优化要点
- 利用主键过滤:如果查询时能指定
job_name的过滤条件(如WHERE job_name = 'job1'或WHERE job_name IN ('job1', 'job2')),MergeTree引擎会通过主键索引快速定位目标数据块,减少不必要的数据扫描,大幅提升查询速度。 - 仅查询必要列:避免使用
SELECT *,只选择业务需要的字段,减少磁盘IO和内存占用。 - 预创建物化视图(高频查询场景):如果该展开查询是高频操作,可创建物化视图提前将数据展开存储,查询时直接读取物化视图,避免每次查询都执行
ARRAY JOIN计算:
CREATE MATERIALIZED VIEW default.ntest2_expanded ENGINE = MergeTree ORDER BY (job_name, `list_data.s`) AS SELECT job_name, item.s AS `list_data.s`, item.e AS `list_data.e`, item.name AS `list_data.name` FROM default.ntest2 ARRAY JOIN list_data AS item
物化视图会在原表写入数据时自动同步展开结果,查询时直接执行SELECT * FROM default.ntest2_expanded即可,性能接近普通表查询。注意:若原表数据更新频繁,物化视图会带来一定的写入开销,需根据业务场景权衡。
内容的提问来源于stack exchange,提问作者Yash Chauhan
相关产品推荐
相关产品推荐

