Clickhouse性能优化

硬件方面
  • 尽量使用性能较好的磁盘,在查询方面,多数场景ssd硬盘性能比机械硬盘块2-3倍
  • CK的高性能与其对CPU的充分利用密不可分,所以尽可能给多的cpu资源可以大大提升查询效率
配置参数调优
参数默认值修改后的值参数说明
max_memory_usage080442450944单个查询在服务器上可使用的最大内存,默认0无限制
max_memory_usage_for_user0140442450944单台服务器上所有查询可使用最大内存,默认0无限制
use_uncompressed_cache01是否使用未压缩块的缓存,可以在处理大量短查询时显著减少延迟并提高吞吐量
max_partitions_per_insert_block100300当个插入最大分区数,超过数值会抛出异常
max_execution_time0600当次查询最大查询时间,0无限制,防止过多慢查询导致服务器雪崩
background_pool_size1632后台线程池大小,建议改成cpu个数的2倍
max_concurrent_queries100200最大并发处理的请求数
max_threads4832设置单个查询能使用的最大cpu根据资源分配情况设置
建表优化
  • 避免使用Nullable类型的,此类型需要额外文件存储,总是会拖累性能并且不能被索引,分区和主键中都无法使用

  • 建表时跟数据的数据类型保持一致,不需要跟hive一样全建string类型的,如数值类型和时间类型,

    不同类型有自己不同的函数且性能有优化

  • 分区粒度根据业务特点决定,不宜过粗或过细,一般选择按天分区,或者有限集字段,总数最好控制在1000-10000之间

  • Order by中排序字段根据业务需求,将查询频率大的放在前面,ck使用稀疏索引,基数特别大的不适合做索引,如user字段这种数量有限且查询频率高的可以加在索引中

  • index_granularity 是用来控制索引粒度的 默认是8192,官方建议如非必须不建议调整

  • 如果表中不是必须保留全量历史数据,建议指定TTL,可以免去手动过期历史数据的麻烦。TTL也可以通过ALTER TABLE语句随时修改。

写入方面
  • 尽量不要执行单条或小批量删除和插入操作,这样会产生小分区文件,给后台Merge 任务带来压力

  • 建议每次写入不少于1000行的批量写入,或每秒不超过一个写入请求。当使用tab-separated格式将一份数据写入到MergeTree表中时,写入速度大约为50到200MB/s。如果写入的数据每行为1Kb,那么写入的速度为50,000到200,000行每秒。如果您的行更小,那么写入速度将更高。为了提高写入性能,您可以使用多个INSERT进行并行写入,这将带来线性的性能提升

  • 不要同时写入太多个分区,分区数控制在阈值(max_partitions_per_insert_block)之下,否则写入会抛出异常

  • 对于分布式表写入,建议写本地表,读分布式表,性能高,对zookeeper压力也比较小

查询优化
  • 查询时充分使用分区和索引字段,可以大大减少io压力,提高查询效率

    如根据唯一eventid查询某条数据的详情
    
    扫描全表
    SELECT * FROM A where eventid = '111'
    
    添加分区条件查询(只扫描部分分区的数据)
    SELECT * FROM A where eventid = '111' AND startTime='2021-10-13 00:00:00'
    
  • 数据量太大时应避免使用select * 操作,大部分减少IO的操作比如列裁剪、分区裁剪,join前先过滤等都是通用的加速查询的方式,clickhouse中也适用。

  • join时遵循大表在前的原则,ClickHouse中无论是Left Join 、Right Join还是Inner Join永远都是拿着右表中的每一条记录到左表中查找该记录是否存在,所以右表必须是小表

  • 对于一些确定的数据模型,可将统计指标通过物化视图的方式进行构建,这样可避免数据查询时重复计算的过程并且预聚合后可以大大提高查询效率;物化视图会在有新数据插入时进行更新。

  • 当多表联查时,查询的数据仅从其中一张表出时,可考虑用 IN 操作而不是 JOIN

    使用in (效率更高)
    select a.* from hits_v1 a where a.CounterID in (select CounterID from visits_v1); 
    
    使用 join
    select a.* from hits_v1 a left join visits_v1 b on a.CounterID=b.CounterID;
    
  • 业务场景非强制要求100%准确的基数计量,应该用uniq()函数而不是uniqExact()函数或DISTINCT关键字。uniq()底层采用HyperLogLog实现,能够以低于1%的精度损失换来极大的性能提升.也可以使用uniqCombined函数比uniq性能低但是精确度高,底层使用了3种算法的组合

  • 大规模数据集上的ORDER BY要加LIMIT限制

  • 两张分布式表上的IN和JOIN之前必须加上GLOBAL关键字。如果不加GLOBAL关键字的话,每个节点都会单独发起一次对右表的查询,而右表又是分布式表,就导致右表一共会被查询N2次(N是该分布式表的shard数量),这就是所谓的查询放大,会带来不小的overhead。加上GLOBAL关键字之后,右表只会在接收查询请求的那个节点查询一次,并将其分发到其他节点上

视图和物化视图

数据库中的 视图(View) 指的是通过一张或多张表查询出来的 「逻辑表」 ,本身只是一段 「SQL」 的封装并 「不存储数据」

物化视图(Materialized View) 与普通视图不同的地方在于它是一个查询结果的数据库对象(持久化存储),非常趋近于表;物化视图是数据库中的预计算逻辑+显式缓存,典型的空间换时间思路,所以用得好的话,它可以避免对基础表的频繁查询并复用结果,从而显著提升查询的性能。

场景

CREATE TABLE ailpha.ailpha_ueba_score
(
    `featureTime` DateTime,
    `userKey` String,
    `featureID` String,
    `riskScore` Nullable(Float64),
)
ENGINE = MergeTree
PARTITION BY featureID
ORDER BY (
 featureTime,
 userKey,
 featureID)
SETTINGS index_granularity = 8192

假设该表记录每个用户每分钟的风险得分情况.

问题: 查询每个用户在每个小时中的最高的分数

普通查询

SELECT toStartOfHour(featureTime,'Asia/Shanghai') AS featureTime,userKey, max(riskScore) as maxScore FROM ailpha.ailpha_ueba_score GROUP BY featureTime,userKey ORDER BY userKey,maxScore DESC  LIMIT 10

在这里插入图片描述

物化视图查询

先建物化视图
CREATE MATERIALIZED VIEW ailpha.host_score
ENGINE = AggregatingMergeTree
PARTITION BY toYYYYMMDD(featureTime)
ORDER BY (featureTime,
 userKey) AS
SELECT
    toStartOfHour(featureTime,
 'Asia/Shanghai') AS featureTime,
    userKey,
    maxState(riskScore) AS maxRiskScore
FROM ailpha.ailpha_ueba_score
GROUP BY
    featureTime,
    userKey
    
查询
SELECT   featureTime,userKey, maxMerge(maxRiskScore) as maxScore FROM ailpha.host_score GROUP BY featureTime,userKey ORDER BY userKey,maxScore DESC  LIMIT 10

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-64God2At-1676010387959)(C:\Users\think\AppData\Roaming\Typora\typora-user-images\image-20211012145226169.png)]

可以看到查询时间相差巨大,因为物化视图做了提前聚合,并存储一个状态,在有大量统计聚合的场景中物化视图可以大大提高查询性能

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
点击房(Paginating)是一种常见的数据查询和展示技术,特别是在大数据环境下。在ClickHouse中,有几种方法可以优化分页操作: 1. 使用LIMIT和OFFSET:ClickHouse支持使用LIMIT和OFFSET子句来限制返回结果的数量和指定偏移量。但是,当OFFSET较大时,ClickHouse需要扫描和跳过较多的数据,可能会导致性能下降。为了避免这个问题,可以考虑其他优化方法。 2. 使用主键分页:如果查询中包含主键字段,可以使用主键进行分页操作。ClickHouse的表是按照主键进行排序的,因此使用主键进行分页可以更高效地获取数据。例如,使用WHERE子句和比较运算符来限制主键范围,并结合LIMIT子句来指定分页大小。 3. 使用SAMPLE子句:ClickHouse提供了SAMPLE子句,可以在查询中指定采样比例。如果数据集非常大,但只需要展示一小部分数据,可以使用SAMPLE子句来进行分页。例如,使用SAMPLE 0.1来获取采样比例为10%的数据。 4. 使用合适的数据模型和索引:良好的数据模型设计和适当的索引可以显著提高分页查询的性能。根据具体的查询需求,选择合适的数据模型和创建适当的索引,可以减少数据的扫描和过滤,从而提高分页操作的效率。 需要注意的是,ClickHouse性能优化是一个综合考虑的问题,具体的优化方法和技巧可能因查询的复杂度、数据量、硬件配置等因素而异。因此,根据具体的业务需求和环境特点,选择合适的优化策略是非常重要的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值