更新时间:2024-05-28 GMT+08:00

ClickHouse应用开发建议

合理配置最大并发数

ClickHouse处理速度快是因为采用了并行处理机制,即使一个查询,默认也会用服务器一半的CPU去执行,所以ClickHouse对高并发查询的场景支持的不够。官方默认的最大并发数是100,可以根据实际场景调整并发配置,建议不超过200。

部署负载均衡组件,查询基于负载均衡组件进行,避免单点查询压力太大影响性能

ClickHouse支持连接集群中的任意节点查询,如果查询集中到一台节点,可能会导致该节点的压力过大并且可靠性不高。建议使用ClickHouseBalancer或者其他负载均衡服务,均衡查询负载,提升可靠性。

合理设置分区键,控制分区数在一千以内,分区字段使用整型

  1. 建议使用toYYYYMMDD(表字段pt_d)作为分区键,表字段pt_d是date类型。
  2. 如果业务场景需要做小时分区,使用toYYYYMMDD(表字段pt_d)、toYYYYMMDD(表字段pt_h)做联合分区键,其中toYYYYMMDD(表字段pt_h)是整型小时数。
  3. 如果保存多年数据,建议考虑使用月做分区,例如toYYYYMM(表字段pt_d)。
  4. 综合考虑数据分区粒度、每个批次提交的数据量、数据的保存周期等因素,合理控制part数量。

查询时最常使用且过滤性最高的字段作为主键,依次按照访问频度从高到低、维度基数从小到大来排

数据是按照主键排序存储的,查询的时可以通过主键快速筛选数据,创建表时合理的设置主键能够大大减少读取的数据量,提升查询性能。例如所有的分析,都需要指定业务的id,则可以将业务id字段作为主键的第一个字段。

根据业务场景合理设置稀疏索引粒度

ClickHouse的主键索引采用的是稀疏索引存储,稀疏索引的默认采样粒度是8192行,即每8192行取一条记录在索引文件中。

使用建议:

  1. 索引粒度越小,对于小范围的查询更有效,避免查询资源的浪费。
  2. 索引粒度越大,则索引文件越小,索引文件的处理会更快。
  3. 超过10亿的表索引粒度可设为16384,其他设为8192或者更小值。

本地表建表参考

本地表创建参考:

CREATE TABLE mybase_local.mytable
(
    `did` Int32,
    `app_id` Int32,
    `region` Int32,
    `pt_d` Date
)
ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/mybase_local/mytable', '{replica}')
PARTITION BY toYYYYMMDD(pt_d)
ORDER BY (app_id, region)
SETTINGS index_granularity = 8192, use_minimalistic_part_header_in_zookeeper = 1;

使用说明:

  1. 表引擎选择:

    ReplicatedMergeTree:支持副本特性的MergeTree引擎,也是最常用的引擎。

  2. ZooKeeper上的表信息注册路径,用于区分集群中的不同配置:

    /clickhouse/tables/{shard}/{databaseName}/{tableName}:{shard}是分片名称,{databaseName}是数据库名称,{tableName}是复制表名称。

  1. order by 主键字段:

    查询时最常使用且过滤性最高的字段作为主键。依次按照访问频度从高到低、维度基数从小到大来排。排序字段不宜太多,建议不超过4个,否则merge的压力会较大。排序字段不允许为null,如果存在null值,需要进行数据转换。

  1. partition by 分区字段

    分区键不允许为null,如果字段中有null值,需要进行数据转换。

  1. 表级别的参数配置:

    index_granularity:稀疏索引粒度配置,默认是8192。

    use_minimalistic_part_header_in_zookeeper:ZooKeeper中数据存储是否启动新版本的优化存储方式。

  1. 建表定义可以参考官网链接:https://clickhouse.tech/docs/en/engines/table-engines/mergetree-family/mergetree/

分布式表建表参考

本地表创建参考:
CREATE TABLE mybase.mytable AS mybase_local.mytable
ENGINE = Distributed(cluster_3shards_2replicas, mybase_local, mytable, rand());

使用说明:

  1. 分布式表名称:mybase.mytable。
  2. 本地表名称:mybase_local.mytable。
  3. 通过“AS”关联分布式表和本地表,保证分布式表的字段定义跟本地表一致。
  4. 分布式表引擎的参数说明:

    cluster_3shards_2replicas:逻辑集群名称。

    mybase_local:本地表所在库名。

    mytable:本地表名。

    rand():可选参数,分片键(sharding key),可以是表中一列的原始数据(如did),也可以是函数调用的结果,如随机值rand()。注意该键要尽量保证数据均匀分布,另外一个常用的操作是采用区分度较高的列的哈希值,如intHash64(user_id)。

根据业务场景表的字段选择最小满足的类型使用

数值类型:UInt8/UInt16/UInt32/UInt64, Int8/Int16/Int32/Int64, Float32/Float64等,选择不同长度,性能差别较大。

基于大宽表进行数据分析,不建议使用大表join大表的操作,对分布式join查询转化成本地表的join查询操作,提升性能

ClickHouse分布式join的性能较差,建议在模型侧将数据聚合成大宽表再导入ClickHouse。分布式join的查询转成本地表的join查询,不仅省去大量的节点间数据传播,同时本地表参与计算的数据量也会少很多。业务层再基于所有分片本地join的结果进行数据汇总,性能会有数量级的提升。

设置合理的part大小

min_bytes_to_rebalance_partition_over_jbod参数表示参与在JBOD卷中磁盘之间自动平衡分发part的最小size,该值不能设置得太小或者太大。

若该值设置得太小,小于max_bytes_to_merge_at_max_space_in_pool/1024,那么clickhouse server进程将会启动失败,另外还会引发不必要的part在磁盘间移动。

若该值设置得过大,则很难有part达到这个条件,比如:min_bytes_to_rebalance_partition_over_jbod大于max_data_part_size_bytes(卷中的磁盘可以存储的part的最大大小),则没有part能达到自动平衡的条件。