这是我参与「第五届青训营 」伴学笔记创作活动的第 17 天,今天学习了列存储这一种我之前没有接触过的存储方式,对列存储的原理以及由来、用法有了初步的了解,下面是我的收获
ClickHouse
1.1 数据库基本概念
数据库是结构化信息或数据的有序集合,一般以电子形式存储在计算机系统中。通常由数据库管理系统(DBMS)来控制。在现实中,数据、DBMS及关联应用一起被称为数据库系统.通常简称为数据库
数据库的类型
- 关系数据库:关系型数据库是把数据以表的形式进行储存.然后再各个表之间建立关系,通过这些表之间的关系来操作不同表之间的数据
- 非关系数据库:NoSQL或非关系数据库.支持存储和操作非结构化及半结构化数据相比于关系型数据库,NoSQL没有固定的表结构.且数据之间不存在表与表之间的关系.数据之间可以是独立的
- 单机数据库:在一台计算机上完成数据的存储和查询的数据库系统
- 分布式数据库:分布式数据库由位于不同站点的两个或多个文件组成,数据库可以存储在多台计算机上,位于同一个物理位置,或分散在不同的网络上
以上都是常见的数据库类型,下面介绍列式存储
1.2 列式存储
1.2.1 介绍
即数据存储在数据库是以列的方式存储的
优点
-
数据压缩
- 数据压缩可以使读的数据量更少.在lO密集型计算中获得更大的性能优势
- 相同类型压缩效率更高
- 排序之后压缩效率更高
- 可以针对不同类型使用不同的压缩算法
-
数据选择
- 可以选择特定的列做计算而不是读取所有列
- 对聚合计算友好
-
延迟物化(* 物化:将列数据转换为可以被计算或者输出的行数据或者内存数据结果的过程,物化后的数据通常可以用来做数据过滤,聚合计算, Join)
- 尽可能推迟物化操作的发生
- 缓存友好
- CPU/内存带宽友好
- 可以利用到执行计划和算子的优化
-
向量化
- SIMD
- 数据格式
- 执行模型
行存 vs 列存
1.3 ClickHouse存储设计
1.3.1 表定义和结构
- 分布式表:不存储数据,用于将查询路由到集群的各个节点
- cluster:逻辑集群,由多个节点组成
- shard_key:指导数据写入分布式表时的分布方式
- 本地表:实际存储数据的表
集群架构
引擎架构
存储架构
1.3.2 索引设计
Hash Index
- 将输入的key通过一个HashFunction映射到一组bucket 上
- 每个bucket都包含一个指向一条记录的地址
- 哈希索引在查找的时候只适用于等值比较
B-Tree
- 数据写入是有序的.支持增删查改
- 每个节点有多个孩子节点
- 每个节点都按照升序排列key值
- 每个key有两个指向左右孩子节点的引用
- 左孩子节点保存的key都小于当前key
- 右孩子节点的保存的key都大于当前key
B+Tree
- 所有的数据都存储在叶子节点,非叶子节点只保存key值
- 叶子节点维护到相邻叶子节点的引用
- 可以通过key值做二分查找.也可以通过叶子节点做顺序访问
1.4 应用场景
大宽表存储和查询
- 查询
- 可以建非常多的列
- 可以增加,删除,清空每一列的数据
- 查询的时候引擎可以快速选择需要的列
- 可以将列涉及到的过滤条件下推到存储层从而加速查询
- 动态表结构
- map中的每个key都是一列
- map中的每一列都可以单独的查询
- 使用方式同普通列.可以做任何计算
离线数据分析
- 数据导入
- 数据可以通过spark生成clickhouse格式的文件
- 导入到hdfs上由hive2ch导入工具完成数据导入
- 数据直接导入到各个物理节点
- 数据按列导入
- 保证查询可以及时访问已有数据
- 可以按需加载需要的列
复杂类型查询
- bitmap索引
- Bitmap64类型
- lowcardinality
- 对于低基数列使用字典编码
- 减少数据存储和读写的IO使用
- 可以做运行时的压缩数据过滤