clickhouse插入最佳实践

背景:

对于使用clickhouse来说,和使用mysql等数据库相比,比较需要注意一点是它的数据插入,由于clickhouse后台使用合并各个part分区的方式进行数据合并,所以也就意味着对于ck来说分批插入才是更好的数据插入方式,本文就来对比下客户端分配和使用clickhouse字段的异步插入的优缺点,此处我们只讨论Replicate复制表.

客户端分批

我们可以通过在客户端对数据进行预先分批,比如我们可以在客户端缓存1000条记录,然后再一次性的通过insert values(…)的方式批量插入到ck中
1.这种方式的优点是ck的自动去重功能还在,也就是说如果客户端由于网络原因重试多次插入同一个statement语句的sql,那么ck会自动的去重.
2.关于客户端分批的大小,clickhouse官网建议每批的最小大小至少为1000,比较合理的区间是1w-10w之间,并且每秒插入数不超过1次,也就是每秒最多执行一次insert操作

ck自带的异步插入

使用类似如下的方式开启异步插入以及等待异步插入完成才返回:

INSERT INTO YourTable SETTINGS async_insert=1, wait_for_async_insert=1 VALUES (...

首先async_insert=1表示开启异步插入的功能,也即是客户端insert的数据会被ck缓存,直到满足一下条件之一才会写入ck的part分区中,

  1. async_insert_max_data_size 缓存大小大于这个配置值
  2. async_insert_busy_timeout_ms超时时间到
  3. async_insert_max_query_number每个数据块已经达到配置的insert次数

其次,我们看一下wait_for_async_insert参数,
a.如果这个参数值=1,那么表示客户端插入数据到ck的缓存后,ck服务器不会马上返回响应,服务器只有再缓存flush数据到part分区后才会返回响应,其实从这里可以看出如果要采用=1的参数值,那么应该是使用多线程插入的方式,因为如果单线程的话,明显每一次其实都是等待async_insert_busy_timeout_ms超时时间到才返回响应.
b.如果这个参数=0,那么表示客户端插入数据到ck的缓存后,ck服务器马上返回响应,不会等待缓存的数据flush成part数据,这种方式的弊端是如果服务器在将缓存数据flush成part分区的时候发生错误,那么客户端完全感知不到,此外,如果客户端此时在服务器返回响应后又继续以高频率发送insert数据请求,会导致服务器端的负载压力过高.
其实从这里可知,不论wait_for_async_insert的值是什么,客户端都要控制insert的速度,对于=1来说需要控制多线程insert的速度,对于=0来说,控制单线程insert的速度,不过对于=1来说,Ack确认返回后确切的知道数据已经插入成功了.
最后,异步插入不支持数据去重,也就是当多次重试调用相同的insert语句时,数据会插入多次,而不会进行去重逻辑.

参考文献:
https://clickhouse.com/docs/en/optimize/asynchronous-inserts
https://clickhouse.com/docs/en/optimize/bulk-inserts

你可能感兴趣的:(clickhouse,clickhouse,数据库,服务器)