崭新的数据库架构(New DBMS Architectures)
由 Michael Stonebraker 介绍
被选中的读物
在数据库这个领域里面,最重要的大事很可能就是“一招包打天下”(ont size fits all)时代的终结。而直到2000年的早期,传统的基于磁盘的行存储架构,依旧是随处可见。实际上,供应商们持着锤子,而他们看什么都像钉子(the commercial vendors had a hammer and everything was a nail,改编自马克吐温的名言,代指固定的思维模式反而局限了人的发展)。
而在过去的一十五年之中,数据库行业发生了数次巨大的动荡,这也是我们接下来,即将讨论的内容。
首先数据库社区已经意识到,在数据仓库这个市场里面,列存储,显著优越于行存储。数据仓库,在早期面向顾客零售数据得到市场的认可过后,迅速拓展,延伸到用户的一般数据上面去。数据仓库记录着用户交易的历史信息。而在实际中来看,这就是每一位顾客的“谁-什么-为什么-什么时候-什么地点”的模型。
传统经验的智慧告诉我们,我们应当围绕一个记录交易信息的中心事实表构建数据仓库。而围绕这些中心事实表的对象,就是维度表,它们记载着从中心表中可以提取得到的信息。在零售的场景之中,一张维度表,可以围绕商店,客户,产品,时间展开工作。这种结果就被称为星形模式(star schema)[^3]。如果商店按照其所在区域,来划分类别,则可能设立多级维度表与雪花型模式。
关键对于事实表而言(Fact table),它们往往非常“肥胖”,通常包含一百个甚至更多的属性序列。显而易见,因为要记录的事实很多,它们往往也非常“长”。一般而言,向数据仓库发出来的查询,往往是重复请求(比如,按各个商店的情况构建月度销售报告)和一些“临时安排的,特殊的”(ad hoc)查询的混合体。让我们试举一例,人们可能会希望了解在暴风雪发生的时候,东北部的销售情况,以及在飓风灾害发生期间,大西洋沿岸的销售情况。
除此之外,一般不会有人使用 select * query 来获取事实表中的全部数据。相反,他们往往会指定一个聚合函数,自有100项属性的数据库中析取六项属性。而在下一条查询中,则可能会选择一些不同的数据集合,而且它的筛选条件之中,则基本没有什么局部性。
在这种使用场景之下,相当明显,相较于行存储,列存储从磁盘转移数据到内存的时间,将会有一个16倍,甚至更大的性能提升(6列对100列)。由此构成了不平衡的优势。此外,请让我们思考一下存储块的问题。在列存储的情况下,单独的属性,全部存储于在一个数据块中,而对于行存储而言,则需要100个块。很明显地,压缩算法在单独属性(的列存储)存储块上的工作产出,将会明显好于有100个属性(的行存储)。除此之外,行存储将会在每一条的记录头部,放置一个头部信息(在 SQLServer 中,这大约需要16个字节)。相比之下,列存储并不需要这样的头信息(因为我们非常清楚里面存储着什么,译者注)。
最后一点,基于行的执行器,有一个对应的内部循环,用于检查输出的数据记录是否有效。也正因它需要按照每一条记录的有效性,来做检查,所以这个内部循环的开销,非常昂贵。而与之相对的情况是,列的存储,是选择列并且挑选出符合条件的项。因此,它的内部循环消耗逻辑,是每当处理完一列之后,再展开检查,而不需要每获取一行,就检查一次。所以,基于列的执行器,在CPU的时间上面,更加高效,同时它所牵涉到的从磁盘中牵涉到的数据,也就更少。在绝大多数的实际环境中,列存储的速度是行存储的50~100倍。
早期的列存储项目,包括 Sybase IQ[^5],它在1990年出现,以及MonetDB[^2]。不过,列存储这项技术的历史,可以追溯到1970年代[^1], [^4]。而在2000年,C-Store/Vertica 作为一家资金充足,性能良好的初创公司,开始正式在市场中亮相。而在下一个十年里面,数据仓库市场,总体逐渐从行存储的世界,过渡到列存储的世界。值得一提的事情在于,倘若 Sybase IQ 能够向自身的科技研究上面投入更多的资金,并实现多节点方案的话,它本来是可以,在更早些时候完成这些工作的。即使[^2]难以阅读,而且"让人感到迷茫"(Down in the weeds),但是基于列的存储方案的优势可以在里面找到精彩的讨论。
而第二个激起巨变的原因,在于主存价格的大幅下降。在当前的阶段,我们只需要花费大约25000美元,就可以购买一台1TB的高性能计算集群,而数个TB的集群,则可能只需要大约10万美元。关键的问题在于,OLTP 数据库往往并不是非常庞大。往往1TB的OLTP数据库,就已然非常庞大,它们也是主内存部署的一个候选方案。就如我们在这个章节中提及到的镜像文章(looking glass paper)所阐述的那样,如果我们的数据适合放置于主存之中,那么我们就不应当将其存储于磁盘之上,因为它们的开销,实在是过于昂贵了。
而在实践之中,OLTP 的数据库市场,如今已经成为主流内存数据库的市场。同样的,传统的基于磁盘的行存储数据库,已经逐渐缺乏了竞争力。而为了更为良好地展开工作,并发控制,故障恢复,以及多线程需要被应用起来,我期待 OLTP 在未来的几年中继续蓬勃发展。
而我当前最乐观的预测就是,不会有人再去使用传统的两阶段锁。而基于时间戳的技术,以及多版本并发控制,会变得逐渐流行起来。在这个篇章的第三篇文章之中,讨论了 Hekaton,它实现了一种非常先进的 MVCC 方案。
故障恢复同样是一个必须解决的问题。一般而言,提出来的解决方案就是复制,以及在线故障转移,它们由 Tandem 在大约20年前提出来。传统智慧的做法就是写入一个日志,并且将日志在网络之中进行传输,之后让它们在备份数据库上进行前滚。这种主动-被动的体系架构,在[^6]中被证明,慢于主动-主动模型大约3倍左右。而在主动-主动模型中,事务仅仅只是简单地运行于每一份副本之上。如果一个人选择了主动-主动模型,那么它必须确保,事务在每一台备份服务器上面,都采用相同的顺序来运行。不幸的事情在于,MVCC 选择这种做法。这就激发起了人们,对于确定性并发控制工作的兴趣,这种实现方案,在端到端系统的表现中,可能远远快于MVCC。
而不管怎么说,OLTP 正在向着主内存部署过渡,而新一代的内存数据库,正在逐渐拓展,以便支持这些应用场景。
第三个新的现象,就是“NoSQL”运动。实际上,超过100种数据库,支持着更为广阔的数据模型,同时体现出下面两种特征:
- "开箱即用"(Out of box)的经验。对于编码人员而言,它们能够简单而轻松地被应用于生产环境之上。相较之下,关系型数据库需要预先定义一个模式出来。
- 支持半结构化的数据。如果每一条记录都有着不同的属性值,那么传统的数据库行存储,将会包含非常非常宽的元组,其稀疏性将会特别强,进而导致低下的效率。
这位商业供应商敲响了警钟,它们应当让自己的数据库系统更好地支持与应用诸如 Json 这样的半结构化数据。总而论之,伴随着关系型数据库对上述两者的整合,我期待 NoSQL 市场能够同 SQL 市场整并。
第四个剧变,就是Hadoop/HDFS/Spark等环境的出现,我们将在第六章中对他们进行讨论。
参考
[1] D. S. Batory. On searching transposed files. ACM Transactions on Database Systems (TODS), 4(4), Dec. 1979.
[2] P. A. Boncz, M. Zukowski, and N. Nes. Monetdb/x100: Hyper-pipelining query execution. In CIDR, 2005.
[3] R. Kimball and M. Ross. The data warehouse toolkit: the complete guide to dimensional modeling. John Wiley & Sons,
2011.
[4] R. Lorie and A. Symonds. A relational access method for interactive applications. Courant Computer Science Symposia,
Vol. 6: Data Base Systems, 1971.
[5] R. MacNicol and B. French. Sybase iq multiplex-designed for analytics. In VLDB, 2004.
[6] N. Malviya, A. Weisberg, S. Madden, and M. Stonebraker. Rethinking main memory OLTP recovery. In ICDE, 2014.