如何处理 Clickhouse 的 AggregatingMergeTree 物化视图中的嵌套字段?

Posted

技术标签:

【中文标题】如何处理 Clickhouse 的 AggregatingMergeTree 物化视图中的嵌套字段?【英文标题】:How to handle nested fields in Clickhouse's AggregatingMergeTree Materialized View? 【发布时间】:2020-07-16 16:38:02 【问题描述】:

有没有办法在 AggregatedMergeTree 物化视图中的 Clickhouse 中组合(连接)组中的 Nested 字段?

想象一下,我有一个表,其架构(简化)如下:

CREATE TABLE test
(
    key1 String,
    key2 String,
    clicks Int32,
    points Nested(x Int32, y Int32)
) Engine = Log

我希望能够使用AggregatingMergeTree 生成一个物化视图,通过“连接”它们来组合嵌套字段(好像嵌套记录可以像某些 SQL 方言那样连接为复杂值)。

如果我将其作为查询进行,则有可能:

SELECT 
    key1,
    key2,
    arrayMap(p -> p.1, points) as x,
    arrayMap(p -> p.2, points) as y
FROM
(
    SELECT  
        key1,
        key2,
        groupArray(tuple(x, y)) as points
    FROM
    (
        SELECT 
            key1, key2, points.x as x, points.y as y
        FROM test 
        ARRAY JOIN points
    )
    GROUP BY key1, key2
)

有没有办法在基于AggregatingMergeTree 引擎的物化视图中使用的查询中表达这一点?我能想到的最好的方法是这样的:

CREATE MATERIALIZED VIEW testagg1
  engine = AggregatingMergeTree partition by key1 order by (key1, key2)
AS 
SELECT
    key1,
    key2,
    sumState(clicks) as clicks,
    groupArrayState(points.x) as `points.x`,
    groupArrayState(points.y) as `points.y`
FROM test
GROUP BY key1, key2

然后我可以使用这个查询得到扁平化的表单:

SELECT 
    arrayMap(p -> p.1, arrayZip(x, y)) as x1,
    arrayMap(p -> p.2, arrayZip(x, y)) as y1
FROM
(
    SELECT 
        key1,
        key2,
        groupArrayMerge(`points.x`) as x, 
        groupArrayMerge(`points.y`) as y 
    FROM testagg1
    GROUP BY key1, key2
) as points 
ARRAY JOIN x, y

它有效,但似乎有点复杂。

有没有更简单、更好的方法来做到这一点? 上面使用的groupArrayStategroupArrayMerge 聚合是否保证以保持并行数组中 x/y 字段的相同顺序?

【问题讨论】:

【参考方案1】:

Nested(x Int32, y Int32) -- 是 create table 命令减少数组样板的语法糖。

desc test
┌─name─────┬─type─────────┬
│ key1     │ String       │
│ key2     │ String       │
│ clicks   │ Int32        │
│ points.x │ Array(Int32) │
│ points.y │ Array(Int32) │
└──────────┴──────────────┴

我能想到的最好的方法是这样的: groupArrayState(points.x) 作为points.x, groupArrayState(points.y) as points.y

这是唯一的方法。这是官方/正确的 CH 方式。

上面使用的聚合保证保持相同 并行数组中 x/y 字段的排序?

是的,这是有保证的。

选择 arrayMap(p -> p.1, arrayZip(x, y)) 作为 x1, arrayMap(p -> p.2, arrayZip(x, y)) as y1

和这个一样

选择 x,y

不是吗?

【讨论】:

感谢丹尼斯的快速回复。是的,这个:sql SELECT arrayMap(p -> p.1, arrayZip(x, y)) as x1, arrayMap(p -> p.2, arrayZip(x, y)) as y1 并且您不需要数组映射来提取元组元素。试试select [(1,2),(3,4)] a, a.1, a.2

以上是关于如何处理 Clickhouse 的 AggregatingMergeTree 物化视图中的嵌套字段?的主要内容,如果未能解决你的问题,请参考以下文章

clickhouse实践关于clickhouse对空值的处理总结

如何处理 MaxUploadSizeExceededException

如何处理c#中的错误代码

Akka 如何处理消息版本?

开玩笑测试 - 如何处理 JsonWebToken 响应

c# FileSystemWatcher如何处理多个文件?