行存储,把属于一行的所有列的数据存储在连续的空间即为行存储。
行存储有两个缺点:(1)由于DBMS中磁盘IO的单位是block (oracle中的block大小2K-32K), 如果查询只关心行中的部分列,需要同时读取其它的列,增加了IO;(2)block上的数据类型不一致(多个列的类型可能不一样)使得压缩率低。这两个缺点对数据仓储而言是非常大的限制。
列存储很好的解决了这两个问题。
1. 行存储与列存储的表的组织:
简单来说两者的区别就是如何组织表:
下面来看一个例子:
从上图可以很清楚地看到,行式存储下一张表的数据都是放在一起的,但列式存储下都被分开保存了。所以它们就有了如下这些优缺点:
|
行式存储 |
列式存储 |
优点 |
Ø 数据被保存在一起 Ø INSERT/UPDATE容易 |
Ø 查询时只有涉及到的列会被读取 Ø 投影(projection)很高效 Ø 任何列都能作为索引 |
缺点 |
Ø 选择(Selection)时即使只涉及某几列,所有数据也都会被读取 |
Ø 选择完成时,被选择的列要重新组装 Ø INSERT/UPDATE比较麻烦 |
注:关系型数据库理论回顾 - 选择(Selection)和投影(Projection)
2补充:数据压缩
刚才其实跳过了资料里提到的另一种技术:通过字典表压缩数据。为了方面后面的讲解,这部分也顺带提一下了。
下面中才是那张表本来的样子。经过字典表进行数据压缩后,表中的字符串才都变成数字了。正因为每个字符串在字典表里只出现一次了,所以达到了压缩的目的(有点像规范化和非规范化Normalize和Denomalize)
3查询执行性能
下面就是最牛的图了,通过一条查询的执行过程说明列式存储(以及数据压缩)的优点:
关键步骤如下:
1. 去字典表里找到字符串对应数字(只进行一次字符串比较)。
2. 用数字去列表里匹配,匹配上的位置设为1。
3. 把不同列的匹配结果进行位运算(bit-wise)得到符合所有条件的记录下标。
4. 使用这个下标组装出最终的结果集。
4. bit-wise技术
位图索引在数据存储中是一个非常有用的索引,相比B+树索引而言,位图索引占用的空间极少,且非常适合集合运算,比如count函数。位图索引的缺点是只适用于基数小的列,当列的基数变大以后,位图索引占用的空间非常大。位图索引的另一个缺点是不支持范围查找。
SybaseIQ声称其采用的bit-wise索引解决了位图索引的缺陷,bit-wise索引支持高基数列,且支持范围查找。Sybase为bit-wise技术申请了专利,其专利内容参见《METHOD AND APPARATUSFOR IDNEXING DATABASE COLUMNS WITH BIT VECTORS》。
bit-wise原理
如下图所示,表存在两个列AA和BB。我们现在要在AA上建bit-wise索引。
AA |
BB |
|
row1 |
3 |
… |
row2 |
1 |
… |
row3 |
2 |
… |
row4 |
4 |
… |
row5 |
1 |
… |
生成索引
●计算bit vector的数量
针对AA列,我们用32bit整数(实际上只需3bit来表达,为了描述更通用的情况,所以用了32bit)来表达AA列上的值,我们需要32个bit vector。
●生成bit-wise索引
如下图所示。bit vector中的位图的数量与表中记录的数量一样。
单值查找
假设我们执行条件为where AA=1的查询。1的二进制表示是{0…0,1},分别与bit-vector执行and运算,结果下图。通过结果bit-vector即可获取目标记录,通过bit-vector进行集合运算也是非常方便的,比如count运算。
范围查找
假设我们执行条件为where AA>1的查询。
1)忽略目标值低位连续为1的位
在本例中我们可以忽略最低位。假如查询的条件为where AA > 11,11的二进制表示为{0…1011},则我们可以忽略最低的2位,即第1位和第2位。
2)从低位开始,依次处理目标值的每个bit
设V1是一个bit-vector,大小是表记录的数量,各个bit的值初始化为0。
从低位开始,依次处理目标值的各个bit。如果bit为0,则把V1和索引进行或操作,把结果写入V1;如果bit为1,则把V1和索引进行与操作,把结果写入V1。
如下图所示。由于第1位([0...001]的第1位)被忽略(R1),所以先处理第2个bit,由于第2个bit为0([0...001]的第2位),所以把V1和索引的第2个bit-vector进行或操作,把结果赋值给V1,见R2;然后处理第3个bit,由于第3个bit为0,把R2与索引的第3个bit-vector执行或操作,把结果赋值给V1,见R3;处理第32位以后,V1的值见RA(最终的R列)。RA中值为1的行记为目标记录,即符合条件where AA>1的行。(实际上是没有各Ri的,只有V1,V1直接和bit-vector直接运算,等所有的bit-vector运算完后,得到的V1,就是最终结果了。)
参考文献:
https://blog.csdn.net/qq_26091271/article/details/51778675
https://blog.csdn.net/liaoxiangui/article/details/80596737