动态改变模式的事件数据流到clickhouse

uqjltbpv  于 2021-07-15  发布在  ClickHouse
关注(0)|答案(2)|浏览(313)

我正在评估clickhouse是否用于存储具有可变事件模式的流式事件。事件模式是嵌套的json。新属性可以是不同的数据类型,因此我们无法创建规范化的键值对。
根据文档,每当模式发生更改时,我们都必须显式地更改表的模式,然后插入新记录。由于插入是从多个源worker进行的,添加'if not exists'子句可以帮助最小化争用条件。
有没有人能告诉我们,有没有更好的方法可以通过动态地改变模式来继续向clickhouse中插入事件?有没有办法让clickhouse根据插入的事件推断出更新的模式?

wixjitnu

wixjitnu1#

insert上的每列需要2mb ram。
1000列表在insert时将消耗2gb。
每列=~磁盘上3个文件+=插入时3个随机读/写。
alter table有时会被merges/selects阻塞,可能会在几个小时内执行。
我会从json中挑选出主列(在最常用的地方使用),并将它们放入专用列中。其他列分为k/v-2列(键数组(string)、值数组(string))。否则使用mongodb。

lnxxn5zx

lnxxn5zx2#

在clickhouse中使用一个支持事件中任何类型的修复模式怎么样。例如使用嵌套列或json列。我使用嵌套列对poc进行了尝试,效果很好。首先,我确定了4种不同的数据类型: strings , numbers , booleans 以及 dates .
clickhouse模式如下所示

CREATE TABLE custom_events
(
    // ... Normal columns needed depending on your use case
    attribute_string Nested
    (
        name String,
        value String
    ),
    attribute_number Nested
    (
        name String,
        value Float32
    ),
    attribute_boolean Nested
    (
        name String,
        value UInt8
    ),
    attribute_date Nested
    (
        name String,
        value Datetime('UTC')
    )
)
ENGINE = MergeTree()
ORDER BY (
   ...
);

clickhouse将嵌套的列转换为两个数组类型的列。要使用此架构,您需要按类型对事件字段进行分组,并在继续插入clickhouse之前将其展平。例如,json中的以下事件

{
    "event_id": 1,
    "event_date": "2018-08-02 10:06:23",
    "data": {
        "rides": [
            {
                "km": 93,
                "vehicle": "plane",
                "people": 2.15,
                "finished": true,
                "date": "2019-06-24T18:52:34"
            }
        ]
    }
}

可能会像这样被压扁

{
    "event_id": 1,
    "event_date": "2018-08-02 10:06:23",
    "data.rides.0.km": 93,
    "data.rides.0.vehicle": "plane",
    "data.rides.0.people": 2.15,
    "data.rides.0.finished": true,
    "data.rides.0.date": "2019-06-24T18:52:34"
}

然后你可以像这样插入clickhouse

insert into custom_events VALUES (1, "2018-08-02 10:06:23", 
['data.rides.0.vehicle'], ['plane'], // This is Key and Value for strings
['data.rides.0.km', 'data.rides.0.km'], [93, 2.15] // This is Key and Value for numbers
... // do the same for each data type
)

然后您可以利用clickhouse提供的所有高级功能来查询数据

SELECT
    arrayFilter(x -> ((x.1) = 1), arrayMap((x, y) -> (x LIKE 'data.rides.%.km', y), attribute_number.name, attribute_number.value)).2 AS element,
    event_date
FROM custom_events
WHERE (event_id = 1) AND notEmpty(element)

这个查询没有意义,因为我对字段做了一点修改,但是您可以理解。这样,您就不需要修改模式,并且可以在clickhouse中使用相同的fix模式存储任意json模式。

相关问题