我们继续从软件角度上看外存数据源的性能,来考察数据库的性能特点,在这篇文章中,我们只关心数据的访问性能,而不涉及计算性能。
一、关系数据库
关系数据库也是很常见的数据存储方式。本质上讲,数据库其实也是一种特殊的二进制文件,但它的性能会弱于直接写在操作系统下的文件,主要原因在于数据库通常都要提供数据更新的能力,这就会产生影响性能的因素:
1. 紧凑性与压缩手段
数据库要考虑数据的更新,一般会采用段页式的分块存储,在存储数据时不会把分块完全填满,而会留一小部分空白区用于后续的修改动作。这样,占用的硬盘空间就会比不考虑更新动作的文件更大一点。
因为要更新数据,也很难实现数据压缩。比如上一篇所说的把小整数存成较短字节的方案,如果采用了这种方案,一旦这个小整数被改成了大整数,原来的空间就存不下了,就要把后续数据都向后移动,这会使数据更新成本过高,所以一般数据库都不采用压缩手段,而直接根据数据类型分配空间,也会造成空间的浪费,极端情况会出现占用空间大于文本的现象。
2. 事务一致性带来的复杂性
许多商业数据库还会同时支持OLTP业务,在读取数据时要提供一致性的能力,这会使访问数据的动作复杂度变大很多。同一条数据,由于其它事务的写操作,可能出现多个备份,在读取时数据库要根据事务的启动时刻找到正确的那一个,这是个非常麻烦的动作,对性能影响很大。
另外,前面文章还提到过,按块存储的结构对于分段也不够自由,不象文件那样可以实施更灵活的并行手段,也会导致数据库的性能表现弱于直接 文件。
数据库普遍还有一个IO性能不佳的问题,数据在数据库中运算时性能尚可,但要通过数据库接口取出来就非常慢,实测的情况表明,这个性能经常可能会比用文本存储还慢。对于这个问题,在数据库本身负担不重时,可以采用并行取数的方法来解决,具体细节及代码我们将在以后再详述。
二、NoSQL数据库
NoSQL常常被用作大数据处理,但是,它真地能获得高性能吗?
这要分情况,看进行什么样的处理。
NoSQL产品一般都不提供事务一致性的能力,这是在数据访问时的动作要比关系数据库简单了许多,不需要考虑回滚段、多备份等问题。而且,放弃事务的NoSQL一般也更容易横向扩展,使用更多机器来承载更大的业务量。在这方面,NoSQL确实会有更高的性能,特别是高并发写入时的优势要比关系数据库大得多。
不过,对于单纯的分析型业务,却不完全是这样。
许多分析型关系数据库也不考虑事务一致性的问题,访问动作同样也较为简单。NoSQL不处理事务一致性带来的性能优势,与这些分析型数据库比并没有特别的地方。
NoSQL产品常常使用Key-Value型存储组织,Value的随意性会带来结构多样性的好处,即使用NoSQL存储数据时不需要事先确定数据结构,不象关系数据库那样必须先建个有特定数据结构的表才能使用,这是NoSQL非常方便的地方。
但是,多样性和高性能是一对天生的矛盾!
多样性意味着每条记录的数据结构都可能不一样。在存储数据时同时也要存储结构,增大了存储量,在解析数据时也要去匹配数据结构中的字段,增加大了复杂度。而关系数据库中同一表的数据结构是确定且相同的,结构只要存储一份,解析数据时的字段对应也非常简单,当数据量很大时,这个优势就会非常明显。
大多数Key-Value式的NoSQL产品,只是在用Key寻找Values时性能很好(这只要有个Hash索引就能够用Key找到对应的记录,关系数据库建了索引也可以),但面临需要对数据遍历才能完成的计算时(比如过滤条件不是针对Key的),它的性能就会远远低于确定数据结构的关系数据库。把NoSQL用于高性能大数据分析业务是个错误的选择,但现实中却经常有人在这么用。