13

我在 clickhouse 中有一个事件表(MergeTree),并且想同时运行很多小插入。但是,服务器变得超载且无响应。此外,一些插入物丢失了。clickhouse错误日志中有很多记录:

01:43:01.668 [ 16 ] <Error> events (Merger): Part 201 61109_20161109_240760_266738_51 intersects previous part

有没有办法优化这样的查询?我知道我可以对某些类型的事件使用批量插入。基本上,运行一个包含许多记录的插入,clickhouse 处理得很好。但是,某些事件,例如点击或打开,无法以这种方式处理。

另一个问题:为什么 clickhouse 决定存在类似的记录,而实际上它们不存在?插入时有类似的记录,与索引中的字段相同,但其他字段不同。

我有时还会收到以下错误:

Caused by: ru.yandex.clickhouse.except.ClickHouseUnknownException: ClickHouse exception, message: Connect to localhost:8123 [ip6-localhost/0:0:0:0:0:0:0:1] timed out, host: localhost, port: 8123; Connect to ip6-localhost:8123 [ip6-localhost/0:0:0:0:0:0:0:1] timed out
    ... 36 more

主要是在项目构建期间运行针对 clickhouse 数据库的测试。

4

5 回答 5

17

Clickhouse 对此有特殊类型的表格 - 缓冲区。它存储在内存中,允许许多小插入没有问题。我们每秒有近 200 个不同的插入 - 它工作正常。

缓冲表:

CREATE TABLE logs.log_buffer (rid String, created DateTime, some String, d Date MATERIALIZED toDate(created))
ENGINE = Buffer('logs', 'log_main', 16, 5, 30, 1000, 10000, 1000000, 10000000);

主表:

CREATE TABLE logs.log_main (rid String, created DateTime, some String, d Date) 
ENGINE = MergeTree(d, sipHash128(rid), (created, sipHash128(rid)), 8192);

手册中的详细信息:https ://clickhouse.yandex/docs/en/operations/table_engines/buffer/

于 2018-09-21T05:59:09.813 回答
10

当处理大量小插入到(非复制的)MergeTree 时,这是一个已知问题。

这是一个错误,我们需要调查和修复。

对于解决方法,您应该按照建议批量发送插入:大约每秒一批:https ://clickhouse.tech/docs/en/introduction/performance/#performance-when-inserting-data 。

于 2016-11-17T22:10:55.717 回答
8

我也遇到过类似的问题,虽然没有那么糟糕——每秒插入约 20 次会导致服务器达到较高的负载平均值、内存消耗和 CPU 使用率。我创建了一个缓冲表来缓冲内存中的插入,然后它们会定期刷新到“真实的”磁盘表中。就像魔术一样,一切都很顺利:loadavg、内存和 CPU 使用率下降到正常水平。好消息是您可以对缓冲表运行查询,并从内存和磁盘中取回匹配的行——因此客户端不受缓冲的影响。请参阅https://clickhouse.tech/docs/en/engines/table-engines/special/buffer/

于 2017-07-07T10:12:46.673 回答
0

clickhouse MergeEngines 的设计并不意味着同时进行少量写入。据我所知,MergeTreeparts根据分区将写入表的数据合并到其中,然后重新组织以parts实现更好的聚合读取。如果我们经常做小写,你会遇到另一个异常Merge

Error: 500: Code: 252, e.displayText() = DB::Exception: Too many parts (300). Merges are processing significantly slow

当您尝试理解为什么会引发上述异常时,这个想法会更加清晰。CH需要合并数据,并且可以存在多少个部分有上限!批处理中的每个写入都作为新部分添加,然后最终与分区表合并。

SELECT
    table, count() as cnt
FROM system.parts 
WHERE database = 'dbname' GROUP BY `table` order by cnt desc

上面的查询可以帮助您监控零件,在编写零件时观察零件将如何增加并最终合并。

对于上述情况,我最好的选择是缓冲数据集并定期将其刷新到数据库,但这意味着没有实时分析。

使用缓冲区很好,但是请考虑以下几点:

  • 如果服务器异常重启,缓冲区中的数据就会丢失。
  • FINAL 和 SAMPLE 不能对 Buffer 表正常工作。这些条件被传递到目标表,但不用于处理缓冲区中的数据
  • 向缓冲区添加数据时,其中一个缓冲区被锁定。(所以没有读取)
  • 如果目标表被复制,则在写入 Buffer 表时,复制表的一些预期特征会丢失。(无重复数据删除)

请通读,这是一个特例引擎:https ://clickhouse.tech/docs/en/engines/table-engines/special/buffer/

于 2021-01-06T09:14:48.947 回答
0

或者,您可以使用类似https://github.com/nikepan/clickhouse-bulk的东西:它将缓冲多个插入并根据用户策略将它们全部刷新。

于 2020-01-05T14:26:53.527 回答