ClickHouse概念

  ClickHouse是新生代的 OLAP,尝试使用了很多有趣的实现,虽然仍旧有很多不足,比如不支持数据更新、动态索引较差、查询优化难度高、分布式需要手动设计等问题。但由于它架构简单,整体相对廉价,逐渐得到很多团队的认同,很多互联网企业加入社区,不断改进 ClickHouse。

ClickHouse 属于列式存储数据库,多用于写多读少的场景,它提供了灵活的分布式存储引擎,还有分片、集群等多种模式,供我们搭建的时候按需选择

MySQL 在处理一个 SQL 请求时只能利用一个 CPU。但是 ClickHouse 则会充分利用多核,对本地大量数据做快速的计算,因此 ClickHouse 有更高的数据处理能力(2~30G/s,未压缩数据),但是这也导致它的并发不高,因为一个请求就可以用光所有系统资源

我们刚使用 ClickHouse 的时候,常常碰到查几年的用户行为时,一个 SQL 就会将整个 ClickHouse 卡住,几分钟都没有响应的情况

官方建议 ClickHouse 的查询 QPS 限制在 100 左右,如果我们的查询索引设置得好,几十上百亿的数据可以在 1 秒内将数据统计返回。作为参考,如果换成 MySQL,这个时间至少需要一分钟以上;而如果 ClickHouse 的查询设计得不好,可能等半小时还没有计算完毕,甚至会出现卡死的现象。

所以,你使用 ClickHouse 的场景如果是对用户服务的,最好对这种查询做缓存。而且,界面在加载时要设置 30 秒以上的等待时间,因为我们的请求可能在排队等待别的查询

考虑到如果想提供 1w QPS 查询,极端的情况下需要 100 台 ClickHouse 存储同样的数据,所以建议还是尽量用脚本推送数据结果到缓存中对外服务

如果我们的集群都是小数据,并且能够保证每次查询都可控,ClickHouse 能够支持每秒上万 QPS 的查询,这取决于我们投入多少时间去做优化分析

推荐的优化思路是:基于排序字段做范围查询过滤后,再做聚合查询。你还要注意,需要高并发查询数据的服务和缓慢查询的服务需要隔离开,这样才能提供更好的性能

ClickHouse 学习01 基本原理_列式存储

ClickHouse 学习01 基本原理_列式存储_02

ClickHouse 学习01 基本原理_列式存储_03

ClickHouse 学习01 基本原理_列式存储_04

ClickHouse 学习01 基本原理_列式存储_05

空间换时间,wide part模式,统计计算,并发写入会很快

  当我们大部分数据都是小数据的时候,一条数据拆分成多个列有一些浪费磁盘 IO,因为是小量数据,我们也不会给他太多机器,这种情况推荐使用 compact parts 方式。当我们的数据列很大,需要对某几个列做数据统计分析时,wide part 的列存储更有优势

ClickHouse 如何提高查询效率

新写入的 parts 数据保存在了 data parts 文件夹内,数据一旦写入数据内容,就不会再进行更改。

ClickHouse 学习01 基本原理_列式存储_06

ClickHouse 学习01 基本原理_列式存储_07

ClickHouse 学习01 基本原理_列式存储_08

ClickHouse 学习01 基本原理_列式存储_09

ClickHouse 学习01 基本原理_列式存储_10

ClickHouse 学习01 基本原理_列式存储_11

具体查询过程是这样的,我们先用二分法查找内存里的主键索引,定位到特定的 mark 文件,再根据 mark 查找到对应的 block,将其加载到内存,之后在 block 里找到指定的 granule 开始遍历加工,直到查到需要的数据

同时由于 ClickHouse 允许同一个主键多次 Insert 的,查询出的数据可能会出现同一个主键数据出现多次的情况,需要我们人工对查询后的结果做去重

ClickHouse 学习01 基本原理_列式存储_12

ClickHouse 学习01 基本原理_列式存储_13

ClickHouse 学习01 基本原理_列式存储_14

ClickHouse 学习01 基本原理_列式存储_15

当数据源插入 ClickHouse 数据源表,生成 data parts 数据时,就会触发 View 表。View 表会按我们创建时设置的聚合函数,对插入的数据做批量的聚合。每批数据都会生成一条具体的聚合统计结果并写入磁盘。

当我们查询统计数据时,ClickHouse 会对这些数据再次聚合汇总,才能拿到最终结果对外做展示。这样就实现了指标统计,这个实现方式很符合 ClickHouse 的引擎思路,这很有特色。

分布式表

ClickHouse 学习01 基本原理_列式存储_16

ClickHouse 学习01 基本原理_列式存储_17

为了更好平衡高可用和性能,还是推荐你选择前一种方式。但是由于各个分片为了保证高可用,会先在本地存储一份,然后再同步推送,这很浪费资源。面对这种情况,我们比较推荐的方式是通过类似 proxy 服务转发一层,用这种方式解决节点变更及直连分发问题

ClickHouse 学习01 基本原理_列式存储_18


ClickHouse 通过分片及内存周期顺序落盘,提高了写并发能力;通过后台定期合并 data parts 文件,提高了查询效率;在索引方面,通过稀疏索引缩小了检索数据的颗粒范围,对于不在主键的查询,则是通过跳数索引来减少遍历数据的数据量;另外,ClickHouse 还有多线程并行读取筛选的设计

ClickHouse 学习01 基本原理_列式存储_19