应用场景
- OLTP类型的查询访问的行数比较少,但往往需要大部分的数据列。传统的行式数据库将一个个完整的数据行存储在数据页中。这种方式在磁盘IO上是比较高效的。
- OLAP类型的查询可能需要访问几百万甚至几十亿个数据行,数据量大需要进行压缩,且往往只关心少数几个数据列。这种情况下就需要列式存储。列式存储每一列单独存储,并且同一列里面的数据类型基本是相同,天生适合压缩。
当然,列式数据库不是万能的,每次读取某个数据行时,需要分别从不同的地方读取各个数据列的值,然后合并在一起形成数据行。因此,如果每次查询涉及的数据量较小或者大部分查询都需要整行的数据,列式数据库并不适用。
列式存储vs行式存储
简单来说两者的区别就是如何组织表,具体区别如下:
| 对比项 | 行式存储 | 列式存储 |
|---|---|---|
| 存储 | 每一行数据作为一个整体来存储 | 每一列数据作为一个整体来存储 |
| 存储顺序 | 把一行中的数据值串在一起存储起来,然后再存储下一行的数据 | 把一列中的数据值串在一起存储起来,每列存储的位置分开 |
| 插入/更新 | 只需对一行进行操作,相对容易 | 需要对多个列进行操作,相对麻烦 |
| 索引 | 对个别列建立索引 | 任何列都能作为索引 |
| 查询 | 选择(Select)即使只涉及某几列,所有数据会被读取,存在冗余列 | 查询时只有涉及到的列会被读取,被选择的列要重新组装 |
| 查询适合场景 | 随机查询 | 范围查询(聚合) |
| 应用 | OLTP | OLAP |
从下图可以很清楚地看到,行式存储下一张表的数据都是放在一起顺序保存的,但列式存储下都被分开保存了。
数据压缩
列式存储天生就是适合压缩,因为同一列里面的数据类型基本是相同。经过字典表进行数据压缩后,表中的字符串才都变成数字了。正因为每个字符串在字典表里只出现一次了,所以达到了压缩的目的。
查询性能
通过一条查询的执行过程说明列式存储(以及数据压缩)的优点,下图为:
关键步骤如下:
- 去字典表里找到字符串对应数字(只进行一次字符串比较)。
- 用数字去列表里匹配,匹配上的位置设为1。
- 把不同列的匹配结果进行位运算得到符合所有条件的记录下标。
- 使用这个下标组装出最终的结果集。
索引优化
可以针对列式存储做专门的索引优化。比如,性别列只有两个值,“男”和“女”,可以对这一列建立位图索引:
“男”对应的位图为100101,表示第1、4、6行值为“男”;“女”对应的位图为011010,表示第2、3、5行值为“女”。如果需要查找男性或者女性的个数,只需要统计相应的位图中1出现的次数即可。另外,建立位图索引后0和1的重复度高,可以采用专门的编码方式对其进行压缩。
参考
http://blog.csdn.net/dc_726/article/details/41143175
http://chattool.sinaapp.com/?p=1234