列式存储
数据库的基本概念
数据库是一种结构化的的信息或者数据有序的集合,以电子形式存储再计算机系统中,有 DBMS(数据库管理系统) 来控制,数据 + DBMS + 以及关联的应用 称为数据库系统,简称数据库
数据库的类型
- 关系型数据库 -> 把数据以表的形式进行存储,各个表之间建立联系,并通过这些关系进行数据库的操作
- 非关系型数据库 -> NoSql 支持存储和操作非结构化以及板结构化的数据,它没有固定的数据结构,数据之间可以是独立存在
- 单机数据库 -> 在一台计算机上完成数据的存储以及查询的的数据库系统
- 分布式数据库 -> 由不同的站点多个文件组成,数据存储在多台计算机上,位于同一个物理位置,或者分散在网络中
- OLTP 数据库 -> 是一种高速分析数据库,专为用户执行大量事务
- OLAP 数据库 -> 能够同时分析多个数据维度,更容易分清其中的数据关系
OLAP数据库的功能
- 大量数据的读写,PB 级的存储
- 多维分析,复杂的聚合函数
- 窗口函数,自定义UDF
- 离线 实时分析
SQL 一种编程语言,尤其在关系型数据库中使用,进行数据的查询 操作 定义数据 进行数据的访问控制
一条 查询语句的 SQL 的结构 select expression from table where condition group by expression order by expression
- from 子句包括指定的数据表也可以包含 Json 二层子句来作为数据表的连接设置规则
- where 子句接一个比较谓词,保留的结果为使谓词为 true 的行
- group by 将含有相同的值的行进行合并,通常与聚合函数使用,去除重复的行数
SQL 的优点
- 标准化 ISO和ANSI长期建立使用SQL数据库标准
- 高度非过程化,我们只需要提出需要,不用了解获得结果的过程或者说怎么样获取数据,用户不必要了解存储路径,过程由系统自动完成,减轻负担,提高数据的独立性
- 同一种语法的格式可以使用两种方式,可以直接在终端输入sql命令进行操作,还可以在高级语言中进行使用
- 语言简洁 易学易用 ,只是用简单的关键字便能完成所需要的数据操作
存储引擎
- 管理内存数据结构
索引 内存数据 缓存
- Query cache
- Data cache
- Index cache
- 管理磁盘的数据
- 磁盘数据的文件格式
- 磁盘数据的增删改查
- 读写算子
- 数据读取逻辑
- 数据写入逻辑
列式存储的设计
列式存储的优点
- 数据压缩
- 数据压缩可以使数据的读写量减少,对于 IO 密集型计算获得更大的性能优势
- 相同类型数据的压缩效率高
- 排序之后的的压缩效率更高
- 针对不同的类型使用不同的压缩算法
- LZ4
abcde_bcdefgh_abcdefghXXXX
abcde_(5,4)fgh_(14,5)fghXXXX
- (5,4) 代表向前5个byte怕,匹配到内容长度为4(bcde是一个重复)
- 重复项越多或者越长,压缩率就会越高
- Run-length encoding
- 压缩重复的数据
- 可以在压缩的数据上直接计算
- Delta encoding
- 将数据存储为连续数据之间的差异,不是直接存储数据的本身
- 特定的算子也可以在压缩上进行计算
-
数据选择
- 选择特定的列进行计算,不用读取所用的列
- 对于聚合计算友好
-
延迟物化
- 将数据转化为可以被计算或者输出的行数据或者内存数据的结果的过程,结果可以用于数据过滤 聚合计算 Join
Note: 延迟物化:尽可能推迟物化操作的的发生
延时物化的优点
- 缓存友好
- CPU / 内存带宽友好
- 利用执行计划和算子的优化(filter)
- 保留直接在压缩列做计算的机会
- 进行向量化
- SIMD(single instruction multiple data)
- 对于多核 CPU ,可以一条指令执行多条数据
- 可以使用 SSE 和 AVX 系列指令集(AVX-256bits/512bits;SSE 128bits 寄存器)
- 数据格式
- 因为要处理多个数据,内存是连续的
- 指定数据的类型
- 执行模型
- 按批进行读取
- 调用时指明数据类型
对于我们我们的需求为
- 按列进行读取
- 每种列类型定义数据读写逻辑
- 函数按列类型处理
ClickHose存储
索引设计
Hash index
- 将输入的 key 通过 Hashfunction 映射到桶上
- 每个桶包含一个指向一条记录的地址
- 哈希索引在查找时只适用等值比较
B-Tree
- 数据的写入是有序的 支持增删改查
- 每个节点有多个孩子节点
- 节点按照升序排列 key 值
- 每个 key 有两个指向左右孩子节点的引用
- 左孩子节点的key小于当前key
- 右孩子节点的key大于当前key
B+Tree
- 所有的数据存储在叶子节点,非叶子节点之保存key值
- 叶子节点维护到相邻叶子节点的引用
- 可以通过key进行二分查找,也可以通过叶子节点进行顺序访问
对于数据量庞大时, B(B+)-Tree 的深度太高,索引的数量也会增大 ,这就需要平衡查询和存储的效率,这就用到了 LSM-Tree
Log-Strured merge-tree(LSM Tree) 是一种为大吞吐场景设计的数据结构主要目的在于优化顺序写入
采用的数据结构
- SSTables
- key 按照顺序存储到文件,称为 segment
- 包含多个 segment
- 写入磁盘后的 segment是不可修改,新数据会生成新的 segment
- Memtable
- 内存中的数据保存在 memtable,通过 搜索二叉树实现通常情况下
- 当 memtable 数据到达设定值时,会按顺序写入磁盘
我们需要对数据进行查询时需要通过新的 segment 进行遍历每个key,我们还可以为segme建立索引