1 简介
1.1 定义
ClickHouse是一个用于联机分析(OLAP)的列式数据库管理系统(DBMS)。
ClickHouse最初是为 YandexMetrica 世界第二大Web分析平台 而开发的。多年来一直作为该系统的核心组件被该系统持续使用着。目前为止,该系统在ClickHouse中有超过13万亿条记录,并且每天超过200多亿个事件被处理。它允许直接从原始数据中动态查询并生成报告。
1.2 OLAP场景的关键特征
- 绝大多数是读请求
- 数据以相当大的批次(> 1000行)更新,而不是单行更新;或者根本没有更新。
- 已添加到数据库的数据不能修改。
- 对于读取,从数据库中提取相当多的行,但只提取列的一小部分。
- 宽表,即每个表包含着大量的列
- 查询相对较少(通常每台服务器每秒查询数百次或更少)
- 对于简单查询,允许延迟大约50毫秒
- 列中的数据相对较小:数字和短字符串(例如,每个URL 60个字节)
- 处理单个查询时需要高吞吐量(每台服务器每秒可达数十亿行)
- 事务不是必须的
- 对数据一致性要求低
- 每个查询有一个大表。除了他以外,其他的都很小。
- 查询结果明显小于源数据。换句话说,数据经过过滤或聚合,因此结果适合于单个服务器的RAM中
1.3 测试数据
根据官网的介绍( clickhouse.tech/benchmark/d…
- Vertica的2.63倍(Vertica是一款收费的列式存储数据库)
- InfiniDB的17倍(可伸缩的分析数据库引擎,基于Mysql搭建)
- MonetDB的27倍(开源的列式数据库)
- Hive的126倍
- MySQL的429倍
- Greenplum的10倍
- Spark的1倍
1.4 性能
根据Yandex的内部测试结果,ClickHouse表现出了比同类可比较产品更优的性能。你可以在 这里 查看具体的测试结果。
许多其他的测试也证实这一点。你可以使用互联网搜索到它们,或者你也可以从 我们收集的部分相关连接 中查看。
单个大查询的吞吐量
吞吐量可以使用每秒处理的行数或每秒处理的字节数来衡量。如果数据被放置在page cache中,则一个不太复杂的查询在单个服务器上大约能够以2-10GB/s(未压缩)的速度进行处理(对于简单的查询,速度可以达到30GB/s)。如果数据没有在page cache中的话,那么速度将取决于你的磁盘系统和数据的压缩率。例如,如果一个磁盘允许以400MB/s的速度读取数据,并且数据压缩率是3,则数据的处理速度为1.2GB/s。这意味着,如果你是在提取一个10字节的列,那么它的处理速度大约是1-2亿行每秒。
对于分布式处理,处理速度几乎是线性扩展的,但这受限于聚合或排序的结果不是那么大的情况下。
处理短查询的延迟时间
如果一个查询使用主键并且没有太多行(几十万)进行处理,并且没有查询太多的列,那么在数据被page cache缓存的情况下,它的延迟应该小于50毫秒(在最佳的情况下应该小于10毫秒)。否则,延迟取决于数据的查找次数。如果你当前使用的是HDD,在数据没有加载的情况下,查询所需要的延迟可以通过以下公式计算得知:查找时间(10 ms) * 查询的列的数量 * 查询的数据块的数量。
处理大量短查询的吞吐量
在相同的情况下,ClickHouse可以在单个服务器上每秒处理数百个查询(在最佳的情况下最多可以处理数千个)。但是由于这不适用于分析型场景。因此我们建议每秒最多查询100次。
数据的写入性能
我们建议每次写入不少于1000行的批量写入,或每秒不超过一个写入请求。当使用tab-separated格式将一份数据写入到MergeTree表中时,写入速度大约为50到200MB/s。如果您写入的数据每行为1Kb,那么写入的速度为50,000到200,000行每秒。如果您的行更小,那么写入速度将更高。为了提高写入性能,您可以使用多个INSERT进行并行写入,这将带来线性的性能提升。
1.5 ClickHouse 优缺点,存在的问题和规划(基于版本20.8)
参考文档:www.infoq.cn/article/Vgg…
优点
1)数据压缩比高,存储成本低。
ClickHouse 最大的特点就是快,其他的比如数据压缩比高、存储成本低等等,所以以前我们有很多的功能埋点都集中在 ES 里面,但是从年初开始到现在应该是把所有的 ES 埋点全部转成 ClickHouse,所以根据 ClickHouse 的数据压缩比,首先就可以评估到我们硬件成本比采用 ES 的方案时它至少降低 60%以上,日志在 ES 和 ClickHouse 上面的查询性能这里就不展开对比。
2)支持常用的 SQL 语法,写入速度非常快,适用于大量的数据更新
它的语法跟 MySQL 比较类似,但是它有一个特点就是它的 join 不能太复杂,A 表 join B 表的时候不能直接 join C 表,需要把 A 表 join B 表的 AS 成一个带别名的临时表以后再去 join C 表,所以它的语法主要还是在 join 上面会比较独特。如果你的查询语句很复杂,你的 join 就会看起来很长,所以查询语句可读性不像 SQL 那么好理解。但是它的写入速度非常快,特别适合于像我们的离线数据每天都是几亿几十亿数据量的更新。官方资料介绍它是按照每秒钟 50-200 兆导入速度。
3)依赖稀疏索引,列式存储,CPU/内存的充分利用造就了优秀的计算能力,并且不用考虑左侧原则
它是依赖稀疏索引,列式存储。我们在去取数据的时候,经常会只取某几个字段,按列存储对 IO 比较友好,减少 IO 的次数,也是在查询速度上一个辅助。再就是它很大程度利用了 CPU,我们都知道 MySQL 是单线程获取数据的,但是 ClickHouse 服务器上面有多少个 CPU,它就会用服务器的一半 CPU 去拉,像我们平时用的 40 核或者 32 核的物理机,基本上拿一半的核去拉数据。当然,这个可以修改配置文件每个 query 用多少 CPU。因为它一个查询需要消耗太多的 CPU,所以在高并发上面是一个短板。当然,我们也不需要考虑什么左侧原则之类的,就算你的查询条件不在索引里面,ClickHouse 的查询一样非常快。
缺点
1)不支持事务,没有真正的 update/delete
不支持事务,没有真正的 update/delete,主要还是高并发的短板,所以我们应用都在一些能 Hold 住的场景下。如果对外放在公网,这个 QPS 就可能很难控制,这种场景用 ClickHouse 就要谨慎。
2)不支持高并发,可以根据实际情况修改 qps 相关配置文件
ClickHouse 吃 CPU,可能团队十个人通过执行同一个查询就可以把一台 CPU 40C 的物理机打爆,但是为什么我前面说我们有 700 亿的数据只需要十台物理机就可以扛得住呢?其实我们对 ClickHouse 做了很多保护。
需要解决的问题(基于20.8版本):
1)部分场景下内存泄漏
现在我们遇到的一些问题是当你服务器上面的数据存储超过你的服务器内存时,会存在内存泄漏。但每天就掉一点点,比如说 128g 内存可能 2-3 个月时间可用内存只有 60%左右,但是这个还是在我用 2018 年的版本时候。我们现在也正在灰度升级到今年的 20.9 的版本,看似还是没有解决。
2)历史数据更新的 CPU 消耗问题。
3)死锁问题
我们每天大量的数据更新后为了减少用户端使用的影响,我们都是通过 rename 的方式,但对于有些查询并发比较高的表 rename 的时候会存在死锁的情况,这个在 20.9 的版本中已修复。
建议性问题:
1)如何保证高优先级的表在服务器维护后第一时间投入生产应用的问题?
对于 ClickHouse 一个建议性的问题就是服务器重启以后,如果服务器上面的数据量过大,可能要很久的数据加载,重新整理文件后服务器才可用,所以这个我跟俄罗斯研发团队有过沟通,让表分级,高优先级的表先启动,可以早点让服务器起来后投入生产应用,后面的表可以通过 lazy 的方式加载。
2)新功能的实践:
1)20.9 的新版支持订阅 MySQL 的 binlog 方式同步数据新功能的时间包括现在有订阅 MySQL 的 binlog 方式同步数据方式,这个我们发现最近几个版本都有在修复一些 bug,所以暂时没有应用,但如果这个做好了是可以用于更多的场景,也可以更好的接入实时数据。2)查看执行计划以前的版本只能到服务器上看执行日志,但这个比较费劲,现在可以像 SQL 一样直接看执行计划了。
1.6 ClickHouse 应用小结
参考文档:www.infoq.cn/article/Vgg…
1)数据导入之前要评估好分区字段
ClickHouse 因为是根据分区文件存储的,如果说你的分区字段真实数据粒度很细,数据导入的时候就会把你的物理机打爆。其实数据量可能没有多少,但是因为你用的字段不合理,会产生大量的碎片文件,磁盘空间就会打到底。
2)数据导入提前根据分区做好排序,避免同时写入过多分区导致 clickhouse 内部来不及 Merge
数据导入之前我们做好排序,这样可以降低数据导入后 ClickHouse 后台异步 Merge 的时候涉及到的分区数,肯定是涉及到的分区数越少服务器压力也会越小。
3)左右表 join 的时候要注意数据量的变化
再就是左右表 join 的问题,ClickHouse 它必须要大表在左边,小表在右边。但是我们可能某些业务场景跑着跑着数据量会返过来了,这个时候我们需要有监控能及时发现并修改这个 join 关系。
4)根据数据量以及应用场景评估是否采用分布式
分布式要根据应用场景来,如果你的应用场景向上汇总后数据量已经超过了单物理机的存储或者 CPU/内存瓶颈而不得不采用分布式 ClickHouse 也有很完善的 MPP 架构,但同时你也要维护好你的主 keyboard。
5)监控好服务器的 CPU/内存波动
再就是做好监控,我前面说过 ClickHouse 的 CPU 拉到 60%的时候,基本上你的慢查询马上就出来了,所以我这边是有对 CPU 和内存的波动进行监控的,类似于 dump,这个我们抓下来以后就可以做分析。
6)数据存储磁盘尽量采用 SSD
数据存储尽量用 SSD,因为我之前也开始用过机械硬盘,机械硬盘有一个问题就是当你的服务器要运维以后需要重启,这个时候数据要加载,我们现在单机数据量存储有超过了 200 亿以上,这还是我几个月前统计的。这个数据量如果说用机械硬盘的话,重启一次可能要等上好几个小时服务器才可用,所以尽量用 SSD,重启速度会快很多。
当然重启也有一个问题就是说会导致你的数据合并出现错乱,这是一个坑。所以我每次维护机器的时候,同一个集群我不会同时维护几台机器,我只会一台一台维护,A 机器好了以后会跟它的备用机器对比数据,否则机器起来了,但是数据不一定是对的,并且可能是一大片数据都是不对的。
7)减少数据中文本信息的冗余存储
要减少一些中文信息的冗余存储,因为中文信息会导致整个服务器的 IO 很高,特别是导数据的时候。
8)特别适用于数据量大,查询频次可控的场景,如数据分析、埋点日志系统
对于它的应用,我认为从成本角度来说,就像以前我们有很多业务数据的修改日志,大家开发的时候可能都习惯性的存到 MySQL 里面,但是实际上我认为这种数据非常适合于落到 ClickHouse 里面,比落到 MySQL 里面成本会更低,查询速度会更快。