关系型数据库系统以二维表的形式呈现数据,比如下面的员工表
RowId | EmpId | Lastname | Firstname | Salary |
---|---|---|---|---|
001 | 10 | Smith | Joe | 40000 |
002 | 12 | Jones | Mary | 50000 |
003 | 11 | Johnson | Cathy | 44000 |
004 | 22 | Jones | Bob | 55000 |
上面的格式仅仅存在于理论和逻辑中,事实上存储设备要求数据序列化为某种形式。
我们知道对于硬盘来说,最昂贵的操作是查找。为了提高最终性能,所需要的相关数据应该以某种方式去存储从而使“查找”操作尽可能少。硬盘由一系列规定大小的块(block)组成, 通常足以容纳数据表的几行。通过把相关的行存储在块中,仅仅一定数量的块需要被读取从而最小化了查找的数量。
行式存储
传统的存储方案是按行序列化数据,如下所示
001:10,Smith,Joe,40000;002:12,Jones,Mary,50000;003:11,Johnson,Cathy,44000;004:22,Jones,Bob,55000;行式存储系统被设计为以很少的操作就可以返回整行或整条记录。当我们需要获取关于某个特定对象的信息的时候,比如某个用户的联系信息或某件商品信息,这种设计就相当适用。
但是行式存储不适用于对整个数据集的操作。比如,找出工资在40000到50000之间的记录,行式存储系统可能得找遍这个数据集才能找出匹配的所有记录。当数据量相当大时,这些记录存储于分散的不同的磁盘块中,这样相当多的磁盘操作就变得不可避免了。
为了提高这种类型操作的性能,大多数DBMS数据库系统使用索引技术。它把列的值存储在一起,同时与记录ID关联。如下所示
001:40000;002:50000;003:44000;004:55000;
我们可以看到,这里仅仅存储整个数据集的一部分,一般来说索引比整个主表要小很多。扫描小的数据集所需要的磁盘操作当然减少了。然而,当有新的数据写入数据库时,索引需要维护,这个对系统增加了额外的开销。
有些行式存储数据库被设计为完全运行于内存中,及内存数据库。这样的系统不依赖于磁盘操作,对于整个数据库的任何数据访问具有同等时间. (equal-time access) 这样的系统可能会很简单有效,然而它们管理的数据仅限于存储在内存中。
列式存储
列式存储系统将某一列的所有值序列化在一起,然后是另一列的所有值。对于我们的例表,数据存储结构如下
10:001,12:002,11:003,22:004;Smith:001,Jones:002,Johnson:003,Jones:004;Joe:001,Mary:002,Cathy:003,Bob:004;40000:001,
50000:002,44000:003,55000:004;
这样的结构看起来与行式存储中的索引结构看起来很像,对吧。是的,没错,看起来很接近。
只是,它们之间有显著的区别。行式存储中,主键是rowid(它关联到索引数据);列式存储中,主键是数据本身(关联回rowid),即“数据即索引”。对于常见的查询,如“所有名字叫Jones的人”,仅仅需要一个操作答案将被找到;另外,像一些聚合运算,基于这样的存储结构其性能能得以大幅提高。
Refer to: http://en.wikipedia.org/wiki/Column-oriented_DBMS