TLDR摘要:Clickhouse Kafka引擎,实例化视图不适用于复杂的select语句。
长版:
我正在尝试使用JSONEachRow通过其Kafka引擎向Clickhouse发送大量JSON数据点。但是,物化视图不会正确消耗流。 我有一个用go编写的kafka生产者,它从多个tcp流中获取数据并异步写入kafka队列。
数据流如下:
TCP来源->生产者-> Kafka-> Clickhouse(Kafka引擎)->物化视图-> 目标表
所有这些都有效,到目前为止效果很好。
当我提高输入数据的速度(400,000点/秒)时,我的瓶颈首先出现了,我的生产者无法足够快地向kafka写入数据,并且连接堆积了。所以我希望尝试对数据进行批处理,但是Clickhouse似乎无法将json数组作为输入(https://clickhouse.yandex/docs/en/interfaces/formats/)
因此,我想到了在数据源处批量处理数据点并在实例化视图中转换消息的想法,所以在此之前我有很多单独的消息:
{“ t”:1547457441651445401,“ i”:“ device_2”,“ c”:20001,“ v”:56454654}“}
我现在收到一条消息,该消息是上述内容的倍数,并且已进行字符串化,并在点之间加了换行符。
{“实时”:“ {\” t \“:1547458266855015791,\” i \“:\” device_2 \“,\” c \“:20001,\” v \“:56454654} \ n {\ “ t \”:1547458266855015791,\“ i \”:\“ device_2 \”,\“ c \”:20001,\“ v \”:56454654}“}
这里的目的是使用实例化视图的select语句中的visitParamExtract将字符串解析并将其转换为多个值。
材料化视图:
CREATE MATERIALIZED VIEW ltdb_mat_view TO default.ltdb AS SELECT
visitParamExtractInt(x, 't') AS timestamp,
visitParamExtractString(x, 'i') AS device_id,
visitParamExtractInt(x, 'v') AS value FROM (
SELECT arrayJoin(*) AS x
FROM
(
SELECT splitByChar('\n', realtimes)
FROM kafka_stream_realtimes
) )
它似乎正在做某事,因为当它运行时,kafka_stream_realtimes被清除了,我无法手动查询它,并收到错误消息“ DB :: Exception:无法声明使用者:。”但是数据永远不会进入决赛桌。
摘要:
出于完整性考虑: kafka_stream_realimes:
CREATE TABLE IF NOT EXISTS kafka_stream_realtimes(realtimes String)
ENGINE = Kafka('kafka:9092', 'realtimes', 'groupTest', 'JSONEachRow');
ltdb:
CREATE TABLE default.ltdb (timestamp Int64,device_id String,value Int64) ENGINE = MergeTree()
PARTITION BY toYYYYMMDD(toDateTime(round(timestamp/1000000000)))
ORDER BY (device_id, value)
SETTINGS index_granularity=8192;
答案 0 :(得分:1)
但是看来Clickhouse无法将json数组作为输入
似乎动机是在生产者端进行批量提交。为什么不只对一堆JSON行进行分组并一次性提交呢? ClickHouse将接收这些多行消息并为您解析它们。您可能还需要向Kafka引擎提供kafka_row_delimiter
设置,因为大多数kafka制作者不会在每条消息的末尾附加行定界符。
所以一条消息变成
{ "t": 1547457441651445401,"i": "device_2","c": 20001,"v": 56454654}
{ "t": 1547457441651445402,"i": "device_2","c": 20001,"v": 56454654}
{ "t": 1547457441651445403,"i": "device_2","c": 20001,"v": 56454654}
...