ClickHouse Better Practices

标签: clickhouse better practices | 发表时间:2022-03-13 05:58 | 作者:LittleMagic
出处:https://www.jianshu.com

前言

经过一个月的调研和快速试错,我们的ClickHouse集群已经正式投入生产环境,在此过程中总结出了部分有用的经验,现记录如下。看官可去粗取精,按照自己项目中的实际情况采纳之。(版本为19.16.14.65)

因为我们引入ClickHouse的时间并不算长,还有很多要探索的,因此不敢妄称“最佳实践”,还是叫做“更佳实践”比较好吧。

表相关事项

数据类型
  • 建表时能用数值型或日期时间型表示的字段,就不要用字符串——全String类型在以Hive为中心的数仓建设中常见,但CK环境不应受此影响。
  • 直接用DateTime表示时间列,而不是用整形的时间戳。因为CK中DateTime的底层就是时间戳,效率高,可读性好,且转换函数丰富。
  • 官方已经指出Nullable类型几乎总是会拖累性能,因为存储Nullable列时需要创建一个额外的文件来存储 NULL的标记,并且Nullable列无法被索引。因此除非极特殊情况,应直接使用字段默认值表示空,或者自行指定一个在业务中无意义的值(例如用-1表示没有商品ID)。
分区和索引
  • 事实表必须分区,分区粒度根据业务特点决定,不宜过粗或过细。我们当前都是按天分区,按小时、周、月分区也比较常见(系统表中的query_log、trace_log表默认就是按月分区的)。
  • 必须指定索引列,在绝大多数查询的 WHERE语句中都会用到的列适合作为索引。CK的索引非MySQL的B树索引,而是类似Kafka log风格的稀疏索引,故不用考虑最左原则,但是建议日期列和区分度较低的列在前,区分度较高的列在后。

订正:根据稀疏索引的规律,建议 查询中更经常用做查询条件(WHERE谓词)的列在前,较不经常用做查询条件的列在后。如果有两列在WHERE谓词中出现的频率大致相同,则 基数较大的列(即区分度较高的列)在前,基数较小的列(区分度较低的列)在后。另外, 基数特别大的列(如订单ID等)不建议直接用作索引。

  • 表的索引粒度 index_granularity不建议调整,保持默认值8192即可。
表参数
  • 生产环境中提供线上服务的表均采用复制表与分布式表相结合,即Replicated*MergeTree+Distributed引擎。分布式表的表名为本地表名加上 _all后缀。
  • 如果表中不是必须保留全量历史数据,建议指定TTL,可以免去手动过期历史数据的麻烦。TTL也可以通过 ALTER TABLE语句随时修改。
  • 建议指定 use_minimalistic_part_header_in_zookeeper = 1设置项,能够显著压缩表元数据在ZooKeeper中的存储。该项也可以写入config.xml中的<merge_tree>一节。

查询相关事项

单表查询
  • 所有应用层查询禁止 SELECT *
  • 查询分区表必须指定分区(所谓partition pruning),不能全表查询。
  • 大规模数据集上的ORDER BY要加LIMIT限制。
  • 结果集上的简单运算(例如 SELECT pv, uv, pv / uv as ratio...中的ratio)可以在前端展示时再进行,减少SQL中不必要的虚拟列。
  • 业务场景非强制要求100%准确的基数计量,应该用uniq()函数而不是uniqExact()函数或DISTINCT关键字。uniq()底层采用HyperLogLog实现,能够以低于1%的精度损失换来极大的性能提升。
  • 能够重用的模式化查询(如固定刷新的BI报表、热力图等)一定要做成物化视图,并在物化视图上查询出结果,可以避免大量的重复计算。关于其用法,可参见之前写过的 《物化视图简介与ClickHouse中的应用示例》
多表查询
  • 当两表关联查询只需要从左表出结果时,建议用IN而不是JOIN,即写成 SELECT ... FROM left_table WHERE join_key IN (SELECT ... FROM right_table)的风格。
  • 不管是LEFT、RIGHT还是INNER JOIN操作,小表都必须放在右侧。因为CK默认在大多数情况下都用hash join算法,左表固定为probe table,右表固定为build table且被广播。
  • CK的查询优化器比较弱,JOIN操作的谓词不会下推,因此一定要先做完过滤、聚合等操作,再在结果集上做JOIN。这点与我们写其他平台SQL语句的习惯很不同,初期尤其需要注意。
  • 两张分布式表上的IN和JOIN之前必须加上GLOBAL关键字。如果不加GLOBAL关键字的话,每个节点都会单独发起一次对右表的查询,而右表又是分布式表,就导致右表一共会被查询N 2次(N是该分布式表的shard数量),这就是所谓的查询放大,会带来不小的overhead。加上GLOBAL关键字之后,右表只会在接收查询请求的那个节点查询一次,并将其分发到其他节点上。
负载均衡

对于循环复制拓扑的集群,查询分布式表的负载均衡策略(即 load_balancing)设为first_or_random是最优的,能够充分利用机器page cache的同时,在有replica失败时也能尽量保证负载平均分配。详情可见 这个issue

写入相关事项

  • 写入分布式表的底表,而不直接写分布式表。在之前的 《ClickHouse复制表、分布式表机制与使用方法》一文中已有说明。
  • 不要做小批量零碎的写入,每批次至少千条级别,避免给merge造成太大压力。
  • 不要同时写入太多个分区,或者写入过快(官方给出的阈值为1秒1次),容易因为merge的速度跟不上parts生成的速度而报出"too many parts"的错误。如果正常情况下还会出现此错误,建议在CPU资源允许的情况下适当调大后台任务线程数 background_pool_size,默认值为16。

运维相关事项

CPU

CK的“快”与其对CPU的积极利用密不可分,所以CPU的单核性能和多核性能都要尽量好一点,16核32线程左右且带较高的睿频比较合适。CK设置中的 max_threads参数控制单个查询所能利用的CPU线程数,默认与本机CPU的物理核心数相同,如果服务器是CK独占的,那么就不用改,否则就改小些。

在监控集群时,CPU指标也是最重要的。实测当单个CK Server节点的CPU使用率超过70%时,服务就不太稳定了。

内存

官方文档建议单机物理内存128G左右。实测CK在我们的应用场景下内存占用并不激进,每线程对应1G内存非常绰绰有余,即 max_threads设为20的话, max_memory_usage参数设为20G(懒得打辣么多0了)。为了不干扰系统的正常运行,也应配置所有查询能利用的最大内存参数 max_memory_usage_for_all_queries,取物理内存的80%左右即可。

另外,CK在执行GROUP BY聚合逻辑的过程中很有可能超出内存限制,因此也建议设置 max_bytes_before_external_group_by参数。在内存占用超出此阈值之后,就会spill到磁盘继续操作,且性能没有降低特别多。官方建议将它设置为 max_memory_usage的一半。

存储

CK不太挑存储介质,普通7200rpm SATA HDD都可以用,也可以配置磁盘阵列,建议RAID10或者RAID6。但是如果为了快速响应,或者多数查询的数据量都很大,还是建议上SSD(我们就是如此)。另外,CK还支持基于配置文件的多盘存储、冷热数据分离和存储策略(storage policy)设置,在特定场景下可能会很有用。我们未实操过,不多讲了。

ZooKeeper

千万要调教好ZooKeeper集群,一旦ZK不可用,复制表和分布式表就不可用了。ZK的数据量基本上与CK的数据量成正相关,所以一定要配置自动清理:

  autopurge.purgeInterval = 1
autopurge.snapRetainCount = 5

另外,ZK的log文件和snapshot文件建议分不同的盘存储,尽量减少follower从leader同步的磁盘压力,且余量必须要留足,毕竟硬盘的成本不算高。

The End

上文中还涉及到一些比较重要的知识点,如MergeTree索引的结构,JOIN语句的执行过程,CK与ZK的交互等等,今后有时间会分别写文章详细讲解。

618之前事情一直都会比较多,希望一切顺利。今天先这样吧。

民那晚安晚安。

相关 [clickhouse better practices] 推荐:

ClickHouse Better Practices

- - 简书首页
经过一个月的调研和快速试错,我们的ClickHouse集群已经正式投入生产环境,在此过程中总结出了部分有用的经验,现记录如下. 看官可去粗取精,按照自己项目中的实际情况采纳之. (版本为19.16.14.65). 因为我们引入ClickHouse的时间并不算长,还有很多要探索的,因此不敢妄称“最佳实践”,还是叫做“更佳实践”比较好吧.

[小技巧] JavaScript Cross Browser Best Practices

- - 小惡魔 - 電腦技術 - 工作筆記 - AppleBOY
我們來看看 Javascript 的小技巧. 不要再使用 navigator.userAgent. 簡單來說 Canvas 在 IE9 才有支援,所以針對 IE 部份,我們使用 navigator.userAgent 來判斷. 但是如果遇到 Safari, Chrome, Android, IPad, IPhone 版本呢,也很好解決,就是一直些判斷式,那為什麼不換個角度去想,直接判斷有無 Cnavas 功能即可,透過 Modernizr 套件可以簡單做到.

blong/clickhouse .md at master · xingxing9688/blong · GitHub

- -
https://clickhouse.yandex/tutorial.html快速搭建集群参考. https://clickhouse.yandex/reference_en.html官网文档. https://habrahabr.ru/company/smi2/blog/317682/关于集群配置参考.

让 Gmail 更加好用的另一个非官方 Gmail Better for Chrome

- 韩叙 - 谷奥——探寻谷歌的奥秘
感谢读者 semidio7 的投递. 曾几何时,Gmail上开始出现了无数的广告,在拖慢系统的同时,还损害着我们的心情. 但是Chrome的这个扩展Gmail Better就可以将这一切恢复如初,一如当初的一般清爽的Gmail界面. 移动联系人和任务列表至页面顶端. 去除搜索网页按钮(中文版中无效).

Chrome 官方感人广告视频 “It Gets Better”

- fantasticfears - 谷奥——探寻谷歌的奥秘
除了“亲耐滴 Sophie”广告,Google还同时推出了另外一段Chrome广告视频:“It Gets Better”. 同样是走温情路线,这个视频的创意来自于同性恋权利活动家Dan Savage在YouTube上创建的It Gets Better频道,Savage利用这个频道鼓励大家上传视频以鼓励那些同性恋青少年.

Best Performance Practices for Hibernate 5 and Spring Boot 2 (Part 1) - DZone Java

- -
Description:If not, then is important to know that attributes can be loaded lazily, as well via Hibernate bytecode instrumentation (another approach is via subentities).

开源OLAP引擎综评:HAWQ、Presto、ClickHouse

- - InfoQ推荐
谈到大数据就会联想到Hadoop、Spark整个生态的技术栈. 大家都知道开源大数据组件种类众多,其中开源OLAP引擎包含Hive、SparkSQL、Presto、HAWQ、ClickHouse、Impala、Kylin等. 当前企业对大数据的研究与应用日趋理性,那么,如何根据业务特点,选择一个适合自身场景的查询引擎呢.

ClickHouse 权限控制与资源隔离

- - IT瘾-dev
使用clickhouse多半应用在实时数仓项目来支持adhoc查询,为了确保企业数据安全高效的使用,那么权限控制与资源隔离是必不可少的. clickhouse在20.4之后的版本开始支持基于RBAC的访问控制管理;主要包括的功能有:用户创建、角色创建、权限管理以及资源隔离;接下来我们将演示如何使用这些功能.

Greenplum VS ClickHouse (单表11亿数据)

- -
公司的一个报表业务,数据量比较大,用户使用频繁. 为了更好的用户体验,我们之前尝试过多种技术:MongoDB、ElasticSearch、Greenplum 等,但是一直没办法做到大部分查询秒级响应. 前段时间探索了很多大数据产品,无意中发现 ClickHouse,很快就被其极致的性能所吸引. 在一番实验和研究后,我们决定用 ClickHouse 解决这个历史债务.

ClickHouse使用实践与规范

- - IT瘾-dev
ClickHouse作为一款开源列式数据库管理系统(DBMS)近年来备受关注,主要用于数据分析(OLAP)领域. 作者根据以往经验和遇到的问题,总结出一些基本的开发和使用规范,以供使用者参考. 随着公司业务数据量日益增长,数据处理场景日趋复杂,急需一种具有高可用性和高性能的数据库来支持业务发展,ClickHouse是俄罗斯的搜索公司Yandex开源的MPP架构的分析引擎,号称比事务数据库快100-1000倍,最大的特色是高性能的向量化执行引擎,而且功能丰富、可靠性高.