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 的查询,这取决于我们投入多少时间去做优化分析
推荐的优化思路是:基于排序字段做范围查询过滤后,再做聚合查询。你还要注意,需要高并发查询数据的服务和缓慢查询的服务需要隔离开,这样才能提供更好的性能
空间换时间,wide part模式,统计计算,并发写入会很快
当我们大部分数据都是小数据的时候,一条数据拆分成多个列有一些浪费磁盘 IO,因为是小量数据,我们也不会给他太多机器,这种情况推荐使用 compact parts 方式。当我们的数据列很大,需要对某几个列做数据统计分析时,wide part 的列存储更有优势
ClickHouse 如何提高查询效率
新写入的 parts 数据保存在了 data parts 文件夹内,数据一旦写入数据内容,就不会再进行更改。
具体查询过程是这样的,我们先用二分法查找内存里的主键索引,定位到特定的 mark 文件,再根据 mark 查找到对应的 block,将其加载到内存,之后在 block 里找到指定的 granule 开始遍历加工,直到查到需要的数据
同时由于 ClickHouse 允许同一个主键多次 Insert 的,查询出的数据可能会出现同一个主键数据出现多次的情况,需要我们人工对查询后的结果做去重
当数据源插入 ClickHouse 数据源表,生成 data parts 数据时,就会触发 View 表。View 表会按我们创建时设置的聚合函数,对插入的数据做批量的聚合。每批数据都会生成一条具体的聚合统计结果并写入磁盘。
当我们查询统计数据时,ClickHouse 会对这些数据再次聚合汇总,才能拿到最终结果对外做展示。这样就实现了指标统计,这个实现方式很符合 ClickHouse 的引擎思路,这很有特色。
分布式表
为了更好平衡高可用和性能,还是推荐你选择前一种方式。但是由于各个分片为了保证高可用,会先在本地存储一份,然后再同步推送,这很浪费资源。面对这种情况,我们比较推荐的方式是通过类似 proxy 服务转发一层,用这种方式解决节点变更及直连分发问题
ClickHouse 通过分片及内存周期顺序落盘,提高了写并发能力;通过后台定期合并 data parts 文件,提高了查询效率;在索引方面,通过稀疏索引缩小了检索数据的颗粒范围,对于不在主键的查询,则是通过跳数索引来减少遍历数据的数据量;另外,ClickHouse 还有多线程并行读取筛选的设计