列式存储与ClickHouse | 青训营笔记

119 阅读6分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 16 天

昨天直播课讲了列式存储,这个以前确实没有接触过。

一、列式存储和行式存储对比

列式存储是指一列中的数据在存储介质中是连续存储的;行式存储是指一行中的数据在存储介质中是连续存储的。 简单的说,可以把列式数据库认为是每一列都是一个表,这个表只有一列,如果只在该列进行,速度就很快。

image.png

行式存储

传统的行式数据库将一个个完整的数据行存储在数据页中。这种方式在大数据量查询的时候会出现以下问题:

  1. 在没有索引的情况下,会把一行全部查出来,查询会使用大量IO
  2. 虽然建立索引和物化视图可以可以快速定位列,但是也需要花费大量时间

但是如果处理查询时需要用到大部分的数据列,这种方式在磁盘IO上是比较高效的。
一般来说,OLTP(Online Transaction Processing,联机事务处理)应用适合采用这种方式。

列式存储

列式数据库是将同一个数据列的各个值存放在一起。插入某个数据行时,该行的各个数据列的值也会存放到不同的地方。

例如上例中列式数据库只需要读取存储着“时间、商品、销量”的数据列,而行式数据库需要读取所有的数据列。因此,列式数据库大大地提高了OLAP大数据量查询的效率。

当然,列式数据库不是万能的,每次读取某个数据行时,需要分别从不同的地方读取各个数据列的值,然后合并在一起形成数据行。

因此,如果每次查询涉及的数据量较小或者大部分查询都需要整行的数据,列式数据库并不适用。

基于列模式的存储,天然就会具备以下几个优点:

1,自动索引 因为基于列存储,所以每一列本身就相当于索引。所以在做一些需要索引的操作时,就不需要额外的数据结构来为此列创建合适的索引。

2,利于数据压缩

一、大部分列数据基数其实是重复的:例如,因为同一个 author 会发表多篇博客,所以 author 列出现的所有值的基数肯定是小于博客数量的,因此在 author 列的存储上其实是不需要存储博客数量这么大的数据量的;

二、相同的列数据类型一致:这样利于数据结构填充的优化和压缩,而且对于数字列这种数据类型可以采取更多有利的算法去压缩存储

适用场景

  • 行式存储
  1. 关注整张表内容,或者需要经常更新数据
  2. 需要经常读取整行数据
  3. 不需要聚集运算,或者快速查询需求
  4. 数据表本身数据行并不多
  5. 数据表的列本身有太多唯一性的数据
  • 列式存储
  1. 基于一列或比较少的列计算的时候
  2. 经常关注一张表某几列而非整表数据的时候
  3. 数据表拥有非常多的列的时候
  4. 数据表有非常多行数据并且需要聚集运算的时候
  5. 数据表列里有非常多的重复数据,有利于高度压缩

二、ClickHouse

ClickHouse由俄罗斯搜索引擎Yandex于2016年6月发布,开发语言为C++,ClickHouse是一个面向联机分析处理(OLAP)的开源的面向列式存储的DBMS,简称, 与Hadoop、Spark这些巨无霸组件相比,ClickHouse很轻量级,查询性能非常好,使用之后会被它的性能折服,非常值得安利。

ClickHouse适用场景

1.日志数据行为分析

2.标签画像的分析

3.数据集市分层

4.广告系统和实时竞价广告

5.电商和金融行业

6.实时监控和遥感测量

7.商业智能

8.在线游戏

9.信息安全

10.所有的互联网场景

ClickHouse特性

1.真正的列式数据库
2.数据压缩
3.数据的磁盘存储
4.多核并行处理
5.多服务器分布式处理(数据保存在不同的shard上,每一个shard都由一组用于容错的副本组成,可并行查询所有shard)
6.向量引擎(按列的一部分进行处理,高效实用CPU)
7.实时的数据更新(支持在表中定义主键,数据增量有序存储在mergeTree中)
8.索引(按照主键对数据进行排序,毫秒内完成对数据的查找)
9.适合在线查询
10.支持近似计算(允许牺牲精度的情况下低延迟查询)
11.支持数据复制和数据完整性(异步多主复制技术)

ClickHouse缺点

1.没有完整的事务支持
2.缺少高频率低延迟的修改或删除数据的能力
3.不适合通过其检索单行的点查询
4.联机事物处理
5.二进制数据或文件存储
6.键值对数据高效率访问请求

ClickHouse核心概念

1.表引擎(Engine)

表引擎决定了数据在文件系统中的存储方式,常用的也是官方推荐的存储引擎是MergeTree系列,如果需要数据副本的话可以使用ReplicatedMergeTree系列,相当于MergeTree的副本版本。读取集群数据需要使用分布式表引擎Distribute。

2.表分区(Partition)

表中的数据可以按照指定的字段分区存储,每个分区在文件系统中都是都以目录的形式存在。常用时间字段作为分区字段,数据量大的表可以按照小时分区,数据量小的表可以在按照天分区或者月分区,查询时,使用分区字段作为Where条件,可以有效的过滤掉大量非结果集数据。

3.分片(Shard)

一个分片本身就是ClickHouse一个实例节点,分片的本质就是为了提高查询效率,将一份全量的数据分成多份(片),从而降低单节点的数据扫描数量,提高查询性能。

  1. 复制集(Replication)

简单理解就是相同的数据备份,在CK中通过复制集,我们实现保障了数据可靠性外,也通过多副本的方式,增加了CK查询的并发能力。这里一般有2种方式:

(1)基于ZooKeeper的表复制方式;

(2)基于Cluster的复制方式。由于我们推荐的数据写入方式本地表写入,禁止分布式表写入,所以我们的复制表只考虑ZooKeeper的表复制方案。

5.集群(Cluster)

可以使用多个ClickHouse实例组成一个集群,并统一对外提供服务。