Clickhouse 中的多个小插入

Multiple small inserts in clickhouse

我在 clickhouse 中有一个事件 table (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 数据库的测试是 运行。

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

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

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

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

Clickhouse 有特殊类型的 tables - Buffer。它存储在内存中并允许许多小插入而不会出现问题。我们每秒有近 200 个不同的插入 - 它工作正常。

缓冲区table:

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);

主要table:

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/

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

clickhouse MergeEngines 的设计并不是要同时进行小写操作。据我了解,MergeTree 将写入 table 的数据 parts 合并到基于分区的数据中,然后重新组织 parts 以获得更好的聚合读取。如果我们经常进行小写操作,您会遇到另一个异常 Merge

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

当你试图理解为什么会抛出上述异常时,思路会清晰很多。 CH需要合并数据,而且存在多少部分是有上限的!并且批处理中的每个写入都作为一个新部分添加,然后最终与分区 table.

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

上面的查询可以帮助你监控分片,边写边观察分片是如何增加并最终合并的。

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

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

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

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