我们在使用clickhouse时,有时候会在建表时指定分片字段,分片字段如果指定的比较合适会将同类的数据放在同一个文件内,提高批量查询的效率,但是如果分片字段执行的不合适,会导致插入式报错。
批量插入报错
如果分片字段指定的不合适,可能在往clickhouse批量插入数据时,会出现如下报错信息
[BatchInsertXXXModel] sync data xxx err:
SyncInfoData.BatchInsertData err, tableName: t_xxx: code: 252,
message: Too many partitions for single INSERT block (more than
100). The limit is controlled by
'max_partitions_per_insert_block' setting. Large number of
partitions is a common misconception. It will lead to severe
negative performance impact, including slow server startup,
slow INSERT queries and slow SELECT queries. Recommended total
number of partitions for a table is under 1000..10000. Please
note, that partitioning is not intended to speed up SELECT
queries (ORDER BY key is sufficient to make range queries
fast). Partitions are intended for data manipulation (DROP
PARTITION, etc)
核心问题在于,建表时指定的分片字段不合适,插入数据离散型太高导致要插入的数据几乎都不在一个分片下。
分区不是为了加快SELECT查询的速度(ORDER BY键足以使范围查询更快)。分区用于数据操作(DROP PARTITION等)
解决方案:
1、去除建表语句中的分片字段,表不再分片
2、修改分片字段为一个合适的字段,保证数据离散型不要太大
值得注意的是,clickhouse是无法直接对表进行分区字段修改的,只能通过建立新表,数据移动,删除旧表的方式。
如何在clickhouse中更改分区
如:
CREATE TABLE traffic (
`date` Date,
...
) ENGINE = MergeTree(date, (end_time), 8192);
想在没有删除表的情况下更改PARTITION BY toYYYYMMDD(date)字段,如何执行此操作?
由于ALTER 查询不允许分区更改,因此可能的方法是创建一个新表
CREATE TABLE traffic_new
(
`date` Date,
...
)
ENGINE = MergeTree(date, (end_time), 8192)
PARTITION BY toYYYYMMDD(date);
并移动您的数据
INSERT INTO traffic_new SELECT * FROM traffic WHERE column BETWEEN x and xxxx;
如有必要,重命名最终表。是的,这个选项涉及删除旧表(似乎没有办法跳过这一步)