之前数仓和画像的处理都是批处理,一般在夜间进行,花费时间很长,按照脚本和调度去完成,后来的处理称为即时处理,即时处理要求计算的时间非常之短,存放在hive中,肯定是不行的,这种需求既要求从一定的数据量中提取(如果是小数量可以从MySQL提取),同时需要速度快。
这种数据库就需要在hive中和OLAP中同时存储一份,OLAP总体的设计目标就是即席查询,但是不同的数据库之间又有细微的差别,OLAP数据库有
ClickHouse 是俄罗斯的Yandex于2016年开源的列式存储数据库(DBMS),使用C++语言编写,主要用于在线分析处理查询(OLAP),能够使用SQL查询实时生成分析数据报告。
以下面的表为例:
Id | Name | Age |
---|---|---|
1 | 张三 | 18 |
2 | 李四 | 22 |
3 | 王五 | 34 |
采用行式存储时,数据在磁盘上的组织结构为:
好处是想查某个人所有的属性时,可以通过一次磁盘查找加顺序读取就可以。但是当想查所有人的年龄时,需要不停的查找,或者全表扫描才行,遍历的很多数据都是不需要的。
而采用列式存储时,数据在磁盘上的组织结构为:
1 | 2 | 3 | 张三 | 李四 | 王五 | 18 | 22 | 34 |
---|---|---|---|---|---|---|---|---|
这时想查所有人的年龄只需把年龄那一列拿出来就可以了。
MySQL和Oracle都是采用行式存储,因为其数据量小,而号称能存储大量数据的数据库都是采用列式存储的,它压缩比十分高,如果压缩比低,是无法存储海量数据的,数据库的存储格式决定了存储的体积。
行式存储每一行的数据格式不同,有数字,文本,日期型等,很大的问题就是,不同的格式无法采用统一的压缩格式,而列式存储一列是一个数据块,是同一个数据格式,很好的弥补了压缩比低的缺点。
压缩比高好处是同样规模的数据,占用的空间小,可以节省磁盘,更重要的是可以节省内存,对于内存小的可以将更多的数据放到其中,如对于128G内存能够管理的列式存储的数据远远大于行式存储的数据,这样管理行式存储的数据需要分布式,代理中间件等,十分复杂,列式存储可能一台机器就足够了,节省资源。
列式储存的好处:
列式存储的劣势:
基本上是一个比较完整的数据库管理系统,几乎覆盖了标准SQL的大部分语法,包括 DDL和 DML,以及配套的各种函数。
ClickHouse支持的功能:
clickhouse和mysql类似,把表级的存储引擎插件化,根据表的不同需求可以设定不同的存储引擎,不同的存储引擎决定了表是如何存储的。
目前包括MergeTree、日志、接口和其他四大类20多种引擎,MergeTree是ClickHouse最核心的引擎,但它不是一个,而是一个家族。MergeTree相当于一个父类,在它的下面还存在子类,子类的子类,都是以MergeTree进行扩展的。
MySQL也是多引擎数据库,innodb只是其中之一,下面的内容既是ClickHouse的特点,也是MergeTree的特点。
ClickHouse采用类LSM Tree的结构(HBase也使用的这种结构),数据写入后定期在后台合并。通过类LSM tree的结构,但是没有内存表,没有预写日志,ClickHouse在数据导入时全部是顺序append写入磁盘,在后台周期性合并数据到主数据段。顺序写的特性,充分利用了磁盘的吞吐能力,即便在HDD上也有着优异的写入性能。
下面以在图书馆借书为场景解释MySQL和ClickHouse不同的写入方式。
MySQL同步随机写入:还书时,将书放到借书时的位置,如1楼,自然科学类,3排5列。
ClickHouse顺序写入,异步合并:还书时,将书放到还书地点,由管理员整理,放回原位,这样就不会阻塞用户。ClickHouse先将数据写到临时分区中,然后就可以通知用户写入完成,然后在后台再调用一个进行去将临时分区中的数据写入到主分区中,一致性差但用户体验好,极大提高了吞吐量和执行速度。
尤其是当在批量插入的场景下,MySQL是真正的将数据一条一条的写入到数据库中,磁盘一致地在移动,而ClickHouse会将大量的数据直接放到临时分区中,然后用户就可以离开了,之后ClickHouse会调用进程去后台处理。
还有一些其他的数据库,如HBase会顺序预写到预写日志中,elasticsearch会写到事务日志中,redis会写到aof中。
顺序写入会比随机写入快一个数量级,也就是快10倍左右,但在严谨性方面同步随机写入会好一些,代价就是速度慢,所以ClickHouse不支持事务。
官方公开benchmark测试显示能够达到50MB-200MB/s的写入吞吐能力,按照每行100Byte估算,大约相当于50W-200W条/s的写入速度。
不支持常规意义的修改行和删除行数据,如果真的想要修改和删除也可以做到,具体做法:将整个分区的数据加where过滤出来,放到临时分区中,然后将临时分区启用,再insert overwride,看起来是改动了一行数据,但实际上是改变了整个分区。
核心:临时分区,异步合并。
索引:用于查询,通过索引可以查找到数据的具体位置,关系型数据库中默认没有索引,但一般来说每张表都需要加一个主键,主键就是索引,在hive中,分区也相当于一个索引,这两种索引的不同在于粒度。
MySQL一般使用稠密索引,即尽可能的让每一条数据都有一个索引,对应公交车的站牌,可以精确定位到一个地点。
clickhouse使用稀疏索引,索引之间的颗粒度(默认8192行),对应火车站的车站,可以定位到一个范围,想找到具体的数据,还需要在这个范围内进行逐表扫描。
好处:范围查询过滤比较快。
弊端:不适合做点对点查询。
这两种设计思路没有好坏,只有取舍,而语句级多线程就是针对稀疏索引的缺点做的一些优化。
MySQL是多线程,但不是语句级的,其处理任意一条SQL,只使用一个线程,MySQL可以执行多条SQL,所以多线程这个功能也不会浪费,对多条SQL开多个线程,不同SQL之间互相独立。
ClickHouse不同,它会针对一条SQL启动多个线程共同完成,如上图中,会在10101 - 22222,32343 - 76543,76766 - 98345会启动三个线程同时进行查询,在ClickHouse中每一个间隔都称为颗粒,默认为8192行,即一个线程最多扫描8192行。
ClickHouse将数据划分为多个partition,每个partition再进一步划分为多个index granularity(颗粒),然后通过多个CPU核心分别处理其中的一部分来实现并行数据处理。
在这种设计下,单条Query就能利用整机所有CPU。极致的并行处理能力,极大的降低了查询延时。
MySQL一般接受简单、数据量小的查询(业务系统),导致QPS(query per second)相对较高,每个查询的资源较少,只有一个线程对一个查询,但是可以支持更多查询。
ClickHouse适合复杂数据量大的查询(分析系统),QPS不高,每个查询投入的资源更多,多个线程对一个查询,但是支持的查询更少。
**弊端:**clickhouse即使对于大量数据的查询也能够化整为零平行处理。但是有一个弊端就是对于单条查询使用多cpu,就不利于同时并发多条查询。所以对于高qps的查询业务,clickhouse并不是强项。
同样规模的数据,存放在数仓(hive)中成本更少,而存放在ClickHouse中,成本会增加,所以ClickHouse中只存储数仓中dwd、dws层最近的数据,一般以天或月为级别。
所以ClickHouse支持对数据的生存周期进行管理,可以像Redis那样删除掉过期的数据,维持数据的新陈代谢。
一般高成本的数据库都会支持生命周期的管理。
某开源社区精华帖中对几款数据库做了性能对比。
单表查询:
关联查询:
关联查询本质上是一个n * m的扫描,ClickHouse相对聚合操作而言不太擅长扫描,OLAP数据库最好都不要进行join操作,在数据进入到OLAP前,可以在数仓中提前join完成计算,OLAP一般只存储一张大宽表。
结论: clickhouse像很多OLAP数据库一样,单表查询速度优于关联查询,而且clickhouse的两者差距更为明显。
# CentOS取消打开文件数限制
# 在/etc/security/limits.conf 这个文件的末尾加入一下内容:
sudo vim /etc/security/limits.conf
# 在文件末尾添加(需要添加*):
* soft nofile 65536
* hard nofile 65536
* soft nproc 131072
* hard nproc 131072
# CentOS取消SELINUX
# 修改/etc/selinux/config中的SELINUX=disabled后重启
sudo vim /etc/selinux/config
SELINUX=disabled
# 关闭防火墙
# 安装依赖
sudo yum install -y libtool
sudo yum install -y *unixODBC*
# 上传4个文件
clickhouse/clickhouse-client-21.4.6.55-2.noarch.rpm
clickhouse/clickhouse-common-static-21.4.6.55-2.x86_64.rpm
clickhouse/clickhouse-common-static-dbg-21.4.6.55-2.x86_64.rpm
clickhouse/clickhouse-server-21.4.6.55-2.noarch.rpm
# 分别在三台机子上安装这4个rpm文件
sudo rpm -ivh clickhouse-*.rpm
# 修改配置文件:
sudo chmod 751 /etc/clickhouse-server/config.xml
sudo vim /etc/clickhouse-server/config.xml
# 把 0.0.0.0 的注解打开,这样的话才能让clickhouse被除本机以外的服务器访问
# 默认为127.0.0.1,只与本机对接
<!-- Same for hosts without support for IPv6: -->
<!-- <listen_host>0.0.0.0</listen_host> -->
# 启动ClickHouse-Server
sudo systemctl start clickhouse-server
# 查看是否启动成功
ps -ef|grep clickhouse
# 出现以下信息
clickho+ 6844 1 0 16:50 ? 00:00:00 clickhouse-watchdog --config=/etc/clickhouse-server/config.xml --pid-file=/run/clickhouse-server/clickhouse-server.pid
clickho+ 6845 6844 1 16:50 ? 00:00:00 /usr/bin/clickhouse-server --config=/etc/clickhouse-server/config.xml --pid-file=/run/clickhouse-server/clickhouse-server.pid
hzy 6893 1253 0 16:51 pts/1 00:00:00 grep --color=auto clickhouse
# 其中6844进程为启动的进程,负责监听,需要干活时其会将6845唤醒
# 使用client连接server,#其中m代表multile line
clickhouse-client -m
# 关闭开机自启
sudo systemctl disable clickhouse-server
一个ClickHouse会占用800M – 1.2G,如果资源足够可以不关闭开机自启。
clickhouse 文件存储位置: