2 NoSQL潮流

     在这一章中,将一起讨论NoSQL潮流的动机和主要驱动力。以及NoSQL主张的批评和反馈。本章将通过不同的尝试得出结论来分类和描写叙述NoSQL数据库。当中一个分类法将在随后的章节中被提出。


2.1 动机和主要驱动力
     NoSQL这个词汇首先用在1998年对关系数据库排除SQL使用的论文([ Str10 ])。这个词在2009年再次被选出来。并用于非关系数据库拥护者(如Last.fm的开发人员Jon Oskarsson,他组织了三藩的NoSQL见面会)的会议([ Eva09a ])。一个博主。通常被觉得使该词汇流行的人是Rackspace公司员工Eric Evans。后来提出了NoSQL运动的雄心是“寻求替代方案的重点是。要解决关系数据库不适合的问题”([
Eva09b ])。

     本节将讨论这一领域中发展和使用非关系数据库的实践者并展示理论上的成果。此外,将介绍NoSQL运动的起源和主要驱动力。


2.1.1 NoSQL实践者的动机
     在计算机世界杂志一篇关于三藩的NoSQL会面的报道。“NoSQLers来分享他们怎样推翻缓慢而昂贵的关系数据库的暴政,有利于用更有效和更廉价的方法来管理数据。”([Com09a ])。它表示特别是Web2.0初创公司,已经在没有Oracle甚至没有曾经非常流行的MySQL的环境下開始他们的业务。相反,他们建立了自己的数据存储如Amazon的Dynamo([DHJ+07])和Google的Bigtable([CDG+06])来存储和处理大量数据的出现,比方像他们在社交或云计算应用。同一时候。大部分这些数据存储变成开源软件。比如,Cassandra最初是为Facebook的新搜索功能开发的,如今是Apache软件项目的一部分。依据project师Avinash
Lakshman,它在写50GB大的数据库时比MySQL快2500倍([LM09])。
    
     计算机世界的文章总结了经常使用的开发和使用NoSQL数据存储的原因:
    
     避免不必要的复杂性  关系型数据库提供了多种功能和严格的数据一致性。但RDBMS实现的这样的丰富的功能和ACID特性可能对特定应用和需求来说是超配的。
     比如,Adobe的ConnectNow持有三份用户会话数据;这些副本不必须接受RDBMS的全部一致性检查,也不须要持久化。因此,全然足以将它们保存在内存中([Com09b])。
    
     高吞吐  一些NoSQL数据库比传统RDBMS提供更高的数据吞吐率。

比如,列存储Hypertable遵循Google的Bigtable方法,同意本地搜索引擎Zvent储存每天十亿数据单元[Jud09]。再举一个样例,Google每天可以处理20PB存储在Bigtable的数据。通过它的MapReduce方法[Com09b]。


     水平扩展性和在商用硬件上执行  “肯定的,数据量是变得如此巨大,人们在寻找其它的技术”。SpringSourceproject师Jon Travis说([Com09a])。博客作者Jonathan Ellis允许这一观点,提到现有的关系型数据库的三个问题,NoSQL数据库试图解决([Ell09a]):
     1.扩展数据(如Digg的绿色徽章特性(注:不明真相)3TB,Facebook的inbox搜索50GB,eBay总量2PB。注:都是10年数据)
     2.单点性能
     3.刚性模式设计
     与RDBMS相反,大部分NoSQL数据库被设计为在水平方向可扩展,且不依靠高度可用的硬件。机器能够加入和删除(或崩溃),并避免造成如同RDBMS的集群方案中实施数据分片那样的操作努力;一些NoSQL数据甚至提供自己主动分片(如MongoDB截至2010年3月,參见[ Mer10g ])。Javier Soltero,SpringSource的CTO是这样说的:“Oracle会告诉你。使用正确的硬件级别和正确的Oracle
RAC(Real Application Clusters)配置和其它相关软件。能够实现同样的可扩展性。可是以什么代价?”([Com09a])。

尤其是对Web 2.0公司,可扩展性方面的考虑对他们的业务至关重要,就像Last.fm的Johan Oskarsson指出:“Web 2.0公司能够抓住机会,他们须要可扩展性。当你将这两者组合,会使NoSQL很引人注目。

”(Johan Oskarsson。Last.fm的meetup组织者和web开发。參见[Com09a])。

博主Nati Shalom允许:“成本压力也迫使很多组织寻找更具成本效益的替代品,研究表明。基于商用硬件的分布式存储能够比很多现有的高端数据库更可靠”(參见[
Sha09a ]和进一步阅读[ Sha09c ])。

他总结道:“全部的这些导致了一个高效成本的'扩展第一数据库’的需求”。


     避免昂贵的O-R Mapping  大部分的NoSQL数据库被设计成存储要么简单的、要么与关系数据结构相比更类似于面向对象编程语言的数据结构。它们不会使昂贵的对象-关系映射成为必需(如键/值存储或文档存储)。

这对具有低复杂度的数据结构的应用特别重要。因其非常难从关系数据库的特性中受益。

Dare Obasanjo声称“全部你真的须要[作为一个Web开发者]是支持某种程度的查询功能并具有良好的持久性语义的键-值或元组存储。”([Oba09a])。博主和数据库分析师Curt
Monash也在这方面表示:“SQL是过程式代码的一个尴尬的选择,差点儿全部的代码是过程式的。

对用户希望做重的、反复操作的数据而言,映射数据到SQL的成本是值得的。

但当你的数据库结构是很很的简单,SQL可能不是故意的。

”SpringSourceproject师Jon Travis允许:“关系型数据库给你太多。他们强迫你扭曲你的对象数据以适合RDBMS。”(在[Com09a]引用)。


     在一篇计算机世界的博客中,GigaSpaces首席技术官和创始人Nati Shalom指出下面驱动了NoSQL潮流([ Sha09b ]):
     数据库集群的复杂性与成本  他指出,NoSQL数据库被设计成在某种程度上“PC集群能够非常easy和廉价地扩展并避免分片的复杂性和成本”,涉及到将数据库切分为多个表以便在大的集群或网格上执行。

     为更好性能妥协的可靠性  Shalom觉得有“应用程序愿意为更好的性能而在可靠性上妥协的不同场景”。作为一个这种妥协样例,他提到HTTP会话数据“须要在不同的网络server之间共享,但因为数据是临时的。在本质上(当用户登出时它会消失)没有必要将它存储在持久存储中。

     现有“一刀切”的数据库思想是错误的  Shalom觉得“越来越多的应用场景不能用传统的数据库方法来解决”。他觉得。“这样的认识实际上并没有那么新”,由于Michael Stonebraker的研究(见下文)已经有非常多年了。但过去几年,老的“新闻”已经蔓延到了一个更大的社区。Shalom觉得,对传统RDBMS的替代品的实现和研究能够用两个主要趋势解释:
     1.连续增长的数据量(需存储)
     2.在更短的时间内处理大量的数据的需求不断增长
     一些公司特别是Web系的,已经採用NoSQL数据库,Shalom估计随着这些数据存储的成熟,他们会找到自己的方式用于主流开发。博主Dennis Forbes允许这一观点。强调银行的要求不是普遍的,尤其是社交媒体站点有不同的特点:“数据的孤岛”、一个“很低的用户/事务比值”和数据完整性的需求不强。考虑到这些特点,关于社交媒体站点和大型网络应用他有例如以下观点:
     “事实是。Facebook更新状态或推特或Slashdots评论不须要ACID。

仅仅要你的业务和表现层能够有力地处理不一致数据,这并不真的非常重要。

非常明显这不是理想的,而且最好没有不论什么数据损失、不一致或服务中断,可是接受数据丢失或不一致(甚至仅仅是临时的)作为一种可能性,打破了迄今为止关系数据库世界最大的’障碍’,能够产生巨大的灵活性。

     这是很多社交媒体站点的情况:数据的完整性基本是可选的。保证完整性的费用是不必要的开支。成千上万的用户和成千上万的事务后,当你从广告点击赚到钱。你開始寻找优化。”
     Shalom建议小心走向NoSQL解决方式和熟悉他们的详细优势和劣势(比如:业务逻辑处理不一致的能力)。其它。像10gen(MongoDB背后的公司)的David Merriman也强调,数据存储没有一个单一的工具或技术。但数据库领域有一个分裂眼下正在进行中,带来了新的和不同的数据存储。比如商业智能vs.在线事务处理vs.大量二进制数据的持久化([Tec09])。

     简易分布和集中数据模型划分的神话  Shalom进一步提到环绕这一直觉的神话,即数据模型最初设计为一个单一的数据库(集中式数据模型,正如他所指出的)常常不能轻易在数据库server间分区和分散。这意味着,假设没有进一步的努力。应用程序将既无法按需扩展也不能正确工作。Ajatus的专家允许这样的说法。在博客中说,假设数据库会增长。首先应配置复本。此外,随着数据量的进一步增长,数据库分片须要昂贵的系统管理,须要大量资金或財产聘用DBMS供应商来经营分散的数据库([
Aja09 ])。

Shalom报道了2009夏天eBay的一次架构峰会。与会者一致允许。尽管通常情况下,抽象被引入以试图隐藏应用程序(如通过代理层将请求路由到特定的server)中分散和分区问题,“这个抽象无法将应用与分区和分散的现实隔离。故障幅度在一个网络内全然不同于一台机器内的故障。

应用程序须要注意到延迟、分布式故障等,使得它有足够的信息来做出详细的上下文相关的决定。系统是分布式的事实渗透到这样的抽象中。”([ Sha09b ])。因此他建议设计数据模型以适应分区环境,即使最初仅仅有一个集中式数据库server。这样的方法提供的优势是避免极晚且昂贵的应用代码更改。

     Shalom总结,在他看来,DBMS将不会非常快消失。

然而,更专业的解决方式会实用武之地,由于一个“一刀切”的思想以前是而且如今还是对于数据库的错误认识。


     编程语言和开发框架的潮流  博主David Intersimone额外观察了编程语言和开发框架(其提供对数据库訪问的抽象时试图隐藏SQL以及关系数据库的使用([ Int10 ]))的趋势。这一趋势在过去几年的样例包含:
  • Java和.NET世界中的实体关系映射。如Java持久化API(JPA,EJB3规范的一部分,[DKE06],[BO06])。实现如Hibernate([JBo10a])。或带SQLMetal代码生成器的LINQ Framework([BH05])。和从.NET version4 開始的ADO.NET Entity Framework([Mic10])。
  • 相同的,流行的Ruby on Rails框架([HR10])和其它隐藏关系型数据库使用的尝试(如实现RoR中的动态记录模式)
  • NoSQL数据存储以及一些云计算供应商提供的数据库全然省略了关系数据库。

    这种云数据存储的一个样例是Amazon的SimpleDB。一个无模式,基于Erlang的终于一致性的数据存储,其特点是作为一个实体的属性值(EAV)。

    它能够存储大量items的集合,当中items是装载由键值对组成的属性集的hashtable([ Nor09 ])。

     这些NoSQL数据库反应这一趋势。并尝试在他们的API中提供接近于编程语言的数据结构(比如,键/值结构,文档。图表)。

     云计算的需求  在一次採訪中10gen(MongoDB背后的公司)的Dwight Merriman提到了在云计算环境中数据存储的两个主要需求([ Tec09 ]):
     1、高直到差点儿无限的可扩展性。特别是在水平方向
     2、低管理开销
     在他看来,以下几类数据库在云中工作非常好:
  • 数据仓库型特定数据库,为批量数据处理和Map/Reduce作业设计的
  • 简单,可扩展和高速的键值对存储
  • 包括比键值对存储更丰富特性的数据库。填补了传统RDBMS的空白,并提供良好的性能和扩展性(如文档数据库)
     博主Nati Shalom允许Merriman。其实应用领域如云计算等对NoSQL数据库是助力:“过去是仅仅有少数相当高端的组织面对的利基问题。随着社交网络和云计算的引入更为普遍了([ Sha09a ])。

     RDBMS加缓存层模式/工作区 vs. 考虑扩展性从零開始构建系统  在他的文章“MySQL和Memcached:一个时代的结束?”中,Todd Hoff说“在云出现前,关系型数据库为主的世界”的可扩展性是“利用MySQL和memcached”的一个问题:
     “对MySQL分片以处理高写入负载,再memcached中缓存对象以处理高读负载,然后写了大量的胶水代码使其所有工作在一起。那以前是艺术,那以前是必须这样做的。今天很多主要站点的架构仍遵循这样的模式。非常大程度上是由于在投入足够的力气时,它能够工作。”([ Hof10c ])
     但随着可扩展性要求的增长,这些技术越来越不可以适应他们。

此外,随着NoSQL数据存储的发展Hoff得出结论:“看远一点,非常明显MySQL + memcached的时代正在过去。它将坚持一段时间。

旧技术非常少全然消失。

”([ Hof10c ])。

作为样例。他列举了大站点和玩家走向非关系数据存储包含LinkedIn、Amazon、Digg和Twitter。Hoff提到下面使用NoSQL解决方式的原因,已在本文前面解释:

  • 关系数据库在读时计算,这对大型网络应用(如Digg)被觉得是错误的。

    NoSQL数据库因此不提供或避免复杂的读操作。

  • 应用程序的线性特性须要常常等待从数据存储的I/O,这对可扩展性和低响应时间不利。

  • 大数据量和高的生长因子促进Twitter開始使用Cassandra,它被设计为可操作大尺度数据。
  • 此外,像Twitter这种公司执行和维护系统的运营成本不断上升。

    这种规模的网络应用因而“须要一个能够以更自己主动化的方式来发展并高度可用的系统”(在[ hof10c ]引用)。

     因为这些原因以及MySQL和memcached时代的“笨拙性”(Hoff所谓的),如今的大型(网络)应用程序能够利用从头開始建立可扩展性的、非堵塞和异步数据库I/O、海量数据、维护和操作任务的自己主动化处理的系统。他觉得这些系统是更好的替代品,相比RDBMS加对象缓存。

Amazon的James Hamilton允许这一声明。对很多大型站点的可扩展性,从零開始是至关重要的。甚至比与传统RDBMS相比缺少部分特性的劣势更重要:

     “扩展第一的应用程序是那些绝对必须不受约束地扩展。且无约束扩展这件事比很多其它的特性更重要。这些应用有大规模大型站点如Facebook、MySpace、Gmail、Yahoo和Amazon。一些站点实际上是利用关系数据库,但非常多不是。

全部这些服务的共同主题是。扩展比特性更重要。他们没有可能执行在一个单独的RDBMS上。”(參见[ Ham09 ]引用[ Sha09a ])


     昨日的须要 vs. 今日的须要  在关于CouchDB的讨论中,Lehnardt和Lang指出对于数据存储的须要已经发生了非常大的变化([ PLL09 ]。这一论点由Stonebraker进一步迭代,见下文)。

在上世纪60和70年代的数据库被设计为单一的大型高端机器。

与此相反,今天。很多大型(网络)公司使用可能会故障的商用硬件。因此应用程序被设计来处理这种故障,被觉得是“操作的标准模式”。就像Amazon指出的(參见[
DHJ+07。205页])。此外。关系数据库适合的数据是刚性结构的关系。并同意用一个复杂语言表示的动态查询。Lehnhardt和Lang指出,今天。特别是在网络领域。数据既不是严格的结构,也不须要动态查询,大多数应用程序已经使用准备语句或存储过程。因此。数据库内提前定义查询和动态赋值给变量是足够的([ PLL09 ])。

     此外。关系数据库最初设计为集中部署,而不是分布。尽管对集群的强化已被增加,它仍然是通过传统的没有分布式的概念開始设计(像例如以下提出的“网络计算的设施”问题)。作为一个样例,通常同步未有效地实现,而是须要昂贵的协议,如两或三阶段提交。Lehnhardt和Lang看到的还有一个困难是,关系数据库集群的尝试是“透明”的应用。这意味着应用程序不应该包括不论什么它在和一个单独的机器或一个集群进行交谈的概念,全部分布式的方面都试图从应用程序中隐藏。

他们质疑这样的保持应用程序感知不到不论什么分布式的后果的方法,如在著名的八个分布式计算的谬误中描写叙述的([
Gos07 ] ):

     “基本上每一个人,当他们初次构建一个分布式应用程序时,会做出下面八如果。它们在长期执行过程中都被证明是错误的。都会导致大麻烦和痛苦的学习经验:
     1、网络是可靠的
     2、延迟是0
     3、带宽是无限的
     4、网络是安全的
     5、拓扑是不变的
     6、有一个管理员
     7、传输的消耗是0
     8、网络是同构的”

     尽管典型的使用RDBMS的业务应用程序,在大多数情况下,尝试在应用中隐藏分布式细节(比如:通过集群、持久层做对象关系映射),但很多大型网络公司和大部分的NoSQL数据库不追求这样的方法。相反,他们让应用程序知道并利用它们。这在Lehnardt和Lang眼中被觉得是一个范式转变(參见[ PLL09 ])。     

     进一步的动机  除了上面提到的,David Intersimone看到NoSQL潮流的下面三目标([ Int10 ]):
  • 获得较关系数据库小的的开销和内存占用
  • 通过Web技术和RPC调用訪问
  • 数据查询的可选形式


2.1.2 理论工作
     在广泛採用的论文“架构时代的终结”([ SMA+07 ] )中,Michael Stonebraker等得人出结论“现有的RDBMS的代码,试图成为一个’一刀切’解决方式。其实不擅长于不论什么事”。在这样的情况下没有不论什么东西意味着他们能与超越他们“1–2个数量级”([ Sc05 ]、[ SBc+07])的“数据仓库、数据流处理、文本和科学数据库市场的专用引擎”竞争,在他们熟悉的业务数据处理/在线事务处理(OLTP)市场也表现不好,当中一个麻省理工开发的名叫H-Store的原型在TPC-C基准上打败RDBMS将近两个数量级。因为这些结果,他们得出结论。RDBMS是“应退休的25岁的遗留代码,取而代之的是一系列‘从零開始’研发的专用引擎。

数据库管理系统供应商(和研究界)应该開始用一张白纸为明天的要求设计系统。而不是继续为昨天的需求推动代码行和架构设计”。但Stonebraker等人怎样得出这个结论?他们在关系型数据库管理系统中发现什么固有的缺陷?他们为“全然重写”提供什么建议?


     首先,Stonebraker等觉得。RDBMS架构已经超过25年。当时硬件特性、用户需求和数据库市场与今天的不同。

他们指出,“流行的RDBMS所有能追朔到20世纪70年代的System R”:IBM的DB2是一个System R的直系后代,微软的SQL Server从Sybase System 5进化而来(还有一个System R的直系后代)。Oracle在其第一个版本号中实现了System
R的用户界面。因而,System R的架构已经被70年代的硬件特性影响了。那以后。处理器速度、内存和磁盘的大小有显著添加,这些因素今天已经不像过去那样限制程序。然而。硬盘和内存间的带宽并不像CPU速度、内存和磁盘大小那样添加得快。

Stonebraker等批评,硬件领域的发展没有影响RDBMS的架构。尤其是下面的System R的架构特点仍然在今天的RDBMS中能够找到:

  • 面向磁盘的存储和索引结构
  • 多线程来隐藏时延
  • 基于锁的并发控制机制
  • 基于日志的恢复
     在这方面。他们强调说,尽管“过去几年有了一些延伸,包含支持压缩、共享磁盘架构、位图索引、支持用户定义的数据类型和操作,但从一開始就没有不论什么系统的又一次设计”。
     其次,Stonebraker等人指出,自20世纪70年代以来,新的市场和用例已经出现,但可用的仅仅有商业数据处理。

这些新兴市场的样例包含“数据仓库、文本管理和流处理”。“它们的需求与商业数据处理有非常大的不同”。在先前的文章([ Sc05 ])他们已经说明了RDBMS“会在一些应用领域被专业的架构超过一个数量级或很多其它,包含:

  • 文本(专业引擎如Google,Yahoo等)
  • 数据仓库(列存储如Vertica,Monet等)
  • 流处理(流处理引擎如StreamBase和Coral8)
  • 科学和智能数据库(数组存储引擎如MATLAB和ASAP)”
     他们继续注意到。过去几十年用户界面和使用模式也改变了,从“操作员输入查询”的终端到富client和网络应用程序,今天互动查询和直接的SQL接口是罕见的。
     Stonebraker等如今给出了“眼下RDBMS的架构甚至不适合业务数据处理的证据”。他们设计了一个OLTP的DBMS引擎称为H-Store,其在功能上适于跑TPC-C基准。比流行商用DBMS快82倍。基于这种证据,他们总结“它们在不论什么一个市场都没有竞争力。因此,他们应该被视为超过四分之中的一个个世纪的过时技术。全然又一次设计和重构是适当的下一步”。


设计考量

     在一篇关于设计考量的文中。Stonebraker等人解释为什么即使在业务数据处理的老本行内RDBMS也被超越。以及他们自己的DBMS原型H-Store为何能够实现“比现有的RDBMS好得多的性能”。

特别是他们的考虑反映过去几十年的硬件发展,以及它怎样能或应该改变RDBMS的架构以便从更快和更大的硬件中获得优点。也给他们坚持的“全然重写”以注解。


     主内存  与70年代相比,大量的主内存变得廉价,由于“OLTP数据库绝大多数是小于1TB而且增长得相当缓慢”他们得出这种结论:这种数据库是“如今或在不久的将来可以部署在主内存中的”。

Stonebraker等人因此觉得OLTP市场在今天或在不久的将来是内存数据库市场。

他们因此批评,“眼下RDBMS供应商用面向磁盘的解决方式处理主内存问题。总之。摩尔定律的30年已使OLTP应用程序的面向磁盘的体系结构变得过时”。

尽管有些关系数据库在内存中执行(比如TimesTen。SolidDB)。但这些系统也从System
R继承了“包袱”——Stonebraker等人对基于磁盘的恢复日志或动态锁定的称呼,这对这些系统的性能有负面影响。


     多线程和资源控制  如前所述,Stonebraker等人觉得数据库是主内存市场。如今他们表示,事务通常仅仅会影响到仅仅有少数几个须要读/写的数据集(如TPC-C基准測试中最多200读),假设这个数据是保存在内存中且没有磁盘IO或出现用户中断。将是很划算的。因此。他们觉得在这种主内存数据库中不须要多线程执行模型。这使得传统关系数据库中相当多的“具体代码”无关紧要,即多线程系统为了最大限度地提高中央处理器和磁盘的使用。资源管理者限制负载以避免使用消耗资源的和多线程的数据结构如并发B树。“这是一个更可靠的系统,一个有更高性能的系统”,他们说。

为了避免在这样一个单线程系统中长期执行的事务,要求应用程序将此类事务分解为较小的事务。或——在分析的目的下——在为该任务优化过的数据仓库中执行这类事务。


     网格计算和在线扩容  此外,Stonebraker等人概述了70年代共享内存架构、80年代共享磁盘架构、今天和未来的无共享架构的发展,这“通常被称为网格计算或刀片计算”。作为一个结果,Stonebraker等人坚持数据库必须反映这一发展,比方(和最明显的)DBMS网格中多节点间的水平切割。此外。他们主张这样的网格的增量水平扩展应该无需由管理员又一次载入部分或全部数据,也不停机。

他们指出,这些要求显著影响了DBMS的架构,如在不影响执行事务的条件下数据传输的能力,这可能不能非常easy地加入到现有的RDBMS中。但能够在新系统的设计中考虑(像比較新的数据库如Vertica)。


     高可用性  Stonebraker等人陈述的下一主题是高可用性和故障转移。

重新,他们概述了这一问题的历史发展,从线下保存当灾难发生时再恢复的日志磁带,到将日志磁带挂在远程硬件上并提供灾备服务。到今天非常普遍的热备份或多网站解决方式。Stonebraker等人把高可用性和内置的灾难恢复作为一个重要的功能。像他们提到的其他设计问题一样,在这些系统的架构和设计层面考虑。他们特别须要OLTP领域的DBMS具有:

     1、保持多个副本一致。须要在地理位置上分散的系统上无缝执行的能力
     2、開始在系统底层使用无共享的支持,用于代替SMP架构上多计算机的支持
     3、支持无共享架构的最好方式是,用“对等网络环境下的多台机器”以便“负载能够分散在多台机器。机器间的副本可用于容错”。在这种配置中。普通操作下能够利用全部的机器资源,且故障仅仅会导致退化的操作由于仅仅是可用资源较少而已。相比之下。今天的HA解决方式在普通操作下有一个热备份仅仅利用硬件资源的一部分,由于热备机器仅仅是在等待活跃机器死掉。总之“这些观点说明应全然又一次设计RDBMS引擎,使其在新架构下实现点对点的HA”。他们得出这种结论。
     在这样一个Stonebraker等人要求的高可用系统。他们看不到不论什么重做日志的须要,如在一个网站故障的情况下,恢复活动“可在任一网站的数据上刷新”。因此。仅仅须要一个撤销日志以同意回滚事务。这种撤销日志不须要储存超过一个事务的周期。因此,“能够是一个主内存数据结构。在事务提交时被丢弃”。正如“在HA的世界。将没有持久化的重做日志,仅仅有一个短暂的撤销日志”。Stonebraker等人发现还有一个潜在的机会以去掉从重做日志恢复的复杂代码;但他们也承认。这种恢复逻辑仅仅是转化为“当失败网站恢复执行时从执行中网站得到最新数据的新功能”。


     无调整  最后,Stonebraker等人指出当前的RDBMS是在一个“电脑非常贵,人非常廉价的时代”被设计的。

今天恰恰相反。人员成本是一个IT公司的主要支出。他们特别批评说“RDBMS有大量复杂的

性能调整,这是旧时代的过时特性”但仍在使用。由于RDBMS的自己主动调整辅助“不会带来比一个熟练DBA的更好效果”。

为代替提供这类仅仅是为了调整而寻找更好配置的特性,Stonebraker等人须要一个数据库。没有这种调整仅仅有“自我的一切”(自我恢复,自我维护,自我调节等)。



关于事务,处理和环境的考虑

     探讨了自上世纪70年代时设计RDBMS以来IT企业的发展历史,以及这样的发展对架构的影响,Stonebraker等人如今转向其它问题。这些会对系统的性能产生不利影响:
  • 重做日志持久化必须避免,由于它们是“差点儿保证是一个显著的性能瓶颈”。

    在HA/故障恢复系统上面它们能够全然省略。

  • client与数据库之间通过JDBC/ODBC接口的通信是他们提到的下一个引起性能衰退的问题。代替这种接口,他们“提倡在数据库系统中‘在进程内’执行应用程序逻辑,通过存储过程的形式”。以避免“传统的数据库客户机/server模式所隐含的进程间开销”。
  • 他们建议进一步消除撤销日志。“无论实际情况,由于它也将是一个重要的瓶颈”。
  • 解决的下一个性能瓶颈是同意并发訪问的动态锁。动态锁定的成本也应降低或消除。
  • 多线程的数据结构导致事务加锁。

    假设事务的执行时间非常短,一个单线程执行模型能够消除这种闭锁与多线程数据结构的开销,仅仅会“在性能上有小损失”。

  • 最后,两阶段提交(2PC)事务应尽可能避免。由于该协议造成的网络传输回合将导致性能下降,由于它们“通常以毫秒级的时间先后发生”。
     假设这些建议能够被满足。Stonebraker等人随后指出基于OLTP特点的事务和大纲(schema)特性。


事务和大纲特性

     除了以上讨论的硬件特性、线程模型、分布式或可用性要求。Stonebraker等人还指出了数据库大纲的特性以及事务属性也显著影响DBMS的性能。关于数据库大纲和事务,他们觉得DBMS应该利用下面特点:

     树形大纲  是例如以下的数据库大纲:“每个表除了一个叫根的节点。都有且仅仅有一个与祖先节点是1-n关系的连接(join)。

因此,大纲是一个1-n关系的树”。

有此属性的大纲。特别easy在一个网格上的节点之间分布。“这样全部树中的等值连接跨度仅仅有一个单一的网站”。这样的模式的根表通常由它的主键分区并移动到网格的其它节点,使每个节点上有根表的分区以及其它表中该根表分区的主键值所相应的数据。


     受约束树应用(CTA)    在Stonebraker等人的概念中,CTA是一个有着树形大纲的应用程序。且仅仅运行有下列特性的事务:
     1、每个事务类中的每个命令都有根节点主键的相等谓词
     2、“对一个网站而言,每个事务类的每个SQL命令是本地的”
    事务类是“同样的SQL语句和程序逻辑的集合,仅仅有每一个事务的执行时常量不同”。Stonebraker等人在他们的H-Store原型中预先定义了。他们进一步觉得,眼下的OLTP应用通常设计为CTA的,或至少能够以这样的方式将其分解,并建议系统地应用大纲变换以使应用满足CTA([ SMA+07。页1153 ])。这些努力的优点是“CTA能够很有效地执行”。


     单网站事务  仅仅能在一个节点上运行,而不须要与DBMS网格的其它节点进行通信。

如受约束树应用满足这样的属性。


     一次性应用  全然由“可并行运行且不须要在网站中传输中间结果的事务”构成。此外。一次性应用中的查询从不使用更早的查询结果。这些属性同意DBMS分解事务“到一个单网站运行计划的集合,它能够被分派到适当的网站运行”。一个普通的使应用一次性的技术是在网站间进行垂直分表。


     两阶段事务  是指这种事务:包括第一阶段的读取操作,该操作能够依据它的结果导致事务的取消,和第二阶段的写操作,该操作保证不会造成不论什么完整性冲突。

Stonebraker等人说,非常多OLTP事务具有这种属性。因此利用它在他们的H-Store原型中替代撤消日志。


     强两阶段事务  在两阶段事务之外。增加了第二阶段全部网站回滚或完毕事务的属性。

     事务可交换性  由Stonebraker等人定义例如以下:“来自相同或不同的类的两个并发事务可交换,仅当无论怎么交织时单网站的子运行计划都产生相同的终于数据库状态(如果两个事务都提交)”。

     无菌事务类  是“和全部事务类(包含其自身)”可交换的事务类。


H-Store概述

     讨论了数据库管理系统设计时应考虑的參数。Stonebraker等人给出H-Store原型。在TPC-C基准中性能明显优于商业数据库。他们的系统草图不在本文中反复(具体信息能够在[ SMA+07页154 ])。但一些属性应当提及:
  • H-Store执行在网格上
  • 表的每一行在内存中连续存放
  • 使用B树索引
  • 网站被划分成逻辑网站,每一个相应一个CPU核
  • 逻辑网站是全然独立的,具有自己的索引、元组存储和他们所在机器的主内存的分区
  • 单线程工作。事务不可中断
  • 仅同意执行以存储过程实现的提前定义事务
  • 省去了重做日志并试图尽可能避免写撤消日志。假设撤消日志无法避免它在事务提交时被丢弃
  • 假设可能,查询执行计划利用上述讨论的单网站和一次性属性
  • 尝试实现无调整和高可用性需求,以及通过“指定水平分区、复制位置、索引字段的全自己主动物理数据库设计器”实现事务的单网站变换
  • 由于H-Store保存每一个表的多个副本。须要事务地进行更新。读命令能够去表的不论什么副本,而更新是针对全部副本
  • H-Store利用上述事务和大纲特性进行优化,比如在两阶段事务中省略撤消日志


TPC-C基准

     当比較他们的H-Store原型与商业DBMS,Stonebraker等人应用了一些针对基准測试实现的重要技巧。首先。他们在对数据库大纲和它的副本分区时。使用了“分解模式。这样每一个网站都有一个源于一个独特的仓库分区记录的子集”的方法。其次。他们讨论怎样利用上面讨论的事务特性。假设基准将执行“在一个单核心,单CPU的机器”那么“每一事务类会是单网站的,且每一个事务能够执行在一个单线程环境”。在一个“成对HA的网站,全部的事务类都能够当成强两阶段,这意味着全部事物将在这两个网站上成功或中止。

因此,在一个单一的成对HA的网站上。ACID特性能够没有不论什么开销地实现”。通过进一步应用技巧。他们实现“使用[模式分区和复制的]基本策略并用上面描写叙述的技巧增强,全部事物类成为一次性的和强两阶段的。仅仅要我们加一个短延时,ACID特性能够在无不论什么并发控制开销的情况下实现。

     基于此设置,他们实现了比商业DBMS的性能好82倍。

他们还分析了在商业DBMS的性能开销,发现主要是由日志和并发控制引起的。

     据说Stonebraker等人仅实施TPC-C基准測试的一部分,且似乎并未调整TPC-C基准測试使之全然适合商业DBMS,就像他们为自己的H-Store原型做的。虽然他们聘请了专业的DBA调整与H-Store对照的DBMS,并尝试优化系统的日志以同意它更好地运行。

结论

     鉴于他们的分析,Stonebraker等人得出这种结论:“我们正走向一个至少有5个(可能很多其它)专用引擎和‘一刀切’的过时系统死亡的世界”。这适用于关系模型以及它的查询语言SQL。
     Stonebraker等人说与“DBMS世界中仅仅包括业务数据处理”的上世纪70年代相反。现在至少有下面市场须要专用DBMS:
     1、数据仓库  通常有星形或雪花形模式。如“一个中心事实表与周围的维度表作1-n连接。并可能进一步的与第二层的维度表作1-n连接。等等”。这些数据能够非常easy地使用关系模型建模。但Stonebraker等人建议一个实体关系模型对建模和查询来说将更简单、更自然。
     2、流处理  这个市场有不同的需求。即“快速处理信息流[和]关联这种流与存储的数据”。

一个SQL的泛化称为StreamSQL。同意使用SQL的FROM语法混合流和关系型数据。引发了一些热情,并被建议当作此领域的标准。Stonebraker等人还提到在流处理中常常须要流数据是扁平的(如一些新闻机构提供的数据流),但也有层次化结构数据的须要。因此。他们“期待流处理厂商更积极地进军层次数据模型”,“他们一定会偏离Ted
Codd原则”。

     3、文本处理  是一个关系型数据库从未被用到的领域
     4、面向自然科学的数据库  由于基础数据结构的原因更可能支持向量而不是表
     5、半结构化数据  该领域实用的数据模型仍在讨论。

一些建议包含XML大纲(由于其复杂性争论激烈)和RDF

     “当关系模型为‘一刀切’的世界而设计,我们设想的各种专业系统能够让我们又一次思考什么样的数据模型将更适合他们的特定需求”,Stonebraker等总结道。

     关于DBMS查询语言他们反对“一刀切的语言”如SQL,在他们看来,根本没有须要SQL的用例:在OLTP市场即席查询非常少或不须要。应用程序以预备语句方式查询。或查询逻辑以存储过程形式被部署到DBMS中。与此相反,其它DBMS市场如数据仓库须要复杂的即席查询能力,这是SQL不能满足的。为此,Stonebraker等人看不到还须要这种语言。
     针对上述市场中的专业DBMS。他们进一步探讨怎样将这些语言与编程语言集成。且反对“连接到不论什么编程语言”的数据子语言如JDBC和ODBC做的。

“[这]导致了高开销的接口”。Stonebraker等人因此建议“在编程语言中嵌入数据库的功能”。

这种语言嵌入样例包含。上世纪70年代的Pascal R和Rigel,或今天微软在.NET平台的LINQ方法。关于语言整合这种能力。他们喜欢他们所谓的“小语种”如Python,Perl。Ruby和PHP,他们“开放源代码。能够通过社区改进”,此外“比眼下通用的语言(被看作编程语言世界中的一刀切的方案)更easy改动”。他们的H-Store原型中的存储过程计划从C++迁移到Ruby。



2.1.3 主要驱动
     在过去的几年中NoSQL潮流吸引了大量的企业和项目。

特别执行大型和高频站点的大网络公司或企业已经从关系数据库(通常有一个缓冲层典型地如memcached,參见[ Hof10c ],[ Hof10b ])切换到非关系数据存储。样例包含最初由Facebook开发的Cassandra([ Apa10d ])且今天还被Twitter和Digg使用([ Pop10a ]、[ Eur09 ])。LinkedIn开发和使用的Project
Voldemort,存储云服务如NoSQL存储Amazon SimpleDB([ Ama10b ]),以及Ubuntu One,一种基于CouchDB的云存储和同步服务([ Can10c ]、[ Hof10c ])。这些NoSQL数据存储的用户,天然地对他们使用的非关系型解决方式的进一步发展很感兴趣。然而,最流行的NoSQL数据存储所採用的思想是Google的Bigtable([ CDG+06 ])或Amazon的Dynamo([ DHJ+07 ])。Bigtable启示的NoSQL存储通常被称为列存储(比如HyperTable,HBase),而Dynamo主要影响键/值存储(如Cassandra[
Apa10d ]。Redis[ S+10 ],Project Voldemort[ K+10a ])。其它项目追求不同的尝试,如图形数据库形成一类自己的数据存储;和文件存储。这能够被看作是具有附加功能的键/值存储(至少同意键/值对具有不同的、一般是分层的命名空间。提供了“文档”的抽象);后者中至少一个(CouchDB)是现有文档存储如上世纪90年代的Lotus Notes的又一次实现,因此没有结合当前的网络技术进行设计(这被CouchDB开发人员们批评,他们又从零開始实现他们的文档存储,參见[ Apa10c ]、[
PLL09 ])。综上所述,能够得出的结论是NoSQL潮流的先驱主要是大型网络公司或执行大型站点的公司,如Facebook,Google和Amazon([ Oba09a ]),和在这一领域的其它人通过他们的想法和改动以满足自己的需求。



2.2 批评
2.2.1 商业方面的怀疑
     在一篇计算机世界关于三藩的NoSQL见面会的文章。提到一些NoSQL数据库的业务相关的问题。它们中的大多数都是开源软件,被不关心许可证和商业支持问题的开发人员赞赏。

然而,特别是出问题后没有人可责怪的情况会吓到商务人士。

即使在Adobe。开发人员使用Terracotta集群替代关系数据库,也仅仅有在让他们的经理看到了系统启动和执行时才干说服他们(參见[ Com09a ])。


2.2.2 过度宣传的NoSQL
     一些企业開始慎重面对NoSQL,由于这一潮流似乎是一个炒作。潜在地缺乏对承诺的履行。这是一种对新技术唤起热情的普遍怀疑态度。如James Bezdek在IEEE通讯中表述例如以下:
     “每个新的技术开头总是天真愉悦,它的发明者通常淹没在他们自己的想法中;他们最初的同僚体验了大部分狂热的热情。大多数技术过度承诺,往往不是简单地生成资金继续这项工作,资金是科学发展的一个组成部分,除了它,仅仅有最具想象和革命性的想法使它度过胚胎阶段。

炒作是过度承诺的自然伴生,大多数技术高速构建以达到炒作的顶点。之后,差点儿总是对没有得到充分开发的想法的过激反应,这不可避免地导致崩溃。接下去是一个时期的冷嘲热讽。很多新技术的发展到这一点,然后消失。幸存下来的那些是由于有人发现了一个基本思想的好应用(=真实的用户利益)。

”([
For10 ]引用[ Bez93 ])

     三藩NoSQL见面会的參与者给出务实的建议:假设公司有一个关系数据库在工作。而且不切换到NoSQL数据库的话什么都不会失去,那就没有不论什么理由来代替它。即使见面会的组织者,Last.fm的Johan Oskarsson也承认。截至2009年6月Last.fm尚未在生产中使用NoSQL数据库。他还指出NoSQL数据库“眼下和主流企业不相关,但一两年后可能会改变”([ Com09a ])。然而,NoSQL见面会的參与者建议假设可能的话看一下NoSQL方案,它是有意义的(比如,在开发新软件)([
Com09a ])。

博主Dennis Forbes说在非关系型数据存储的发明者和开发人员之间看不见不论什么过度热情(“他们大部分是聪明的。务实的开发人员”),但使用这些技术开发人员却希望“这个潮流解决他们的弱点”。

他——一个为金融、保险、电信、电力等行业做传统的关系数据库开发——却说“无疑是非常多奇异的工作发生的NoSQL阵营中,非常关注可伸缩性”。

还有一方面。在他博客的评论中批评说:“争论的是。聚会的本身。被正在或希望建立非常大的网络公司的人劫持了(都希望成为下一个Facebook)。该领域的价值观和推断投射到整个数据库产业——其包含一系列使社交媒体的边缘样例也相形见绌的解决方式——这真是讽刺”([
For10 ])。(注:不懂,好像是在骂人)


2.2.3 NoSQL没有什么创新
     类似于炒作的论点。对NoSQL的还有一种批评是。NoSQL数据库没什么创新由于其它尝试如对象数据库已经存在了几十年。作为这个争论的样例,博主David Intersimone提到Lotus Notes能够归入早期的文档存储,且支持分布和复制而有利于并发控制的性能(除非另有说明,[ Int10 ])。一个特别有意思的样例是,CouchDB的主要开发人员,Damien Katz,曾为Lotus Notes工作几年。

NoSQL的拥护者觉得CouchDB是“Notes的成功”。由于Notes的分布特征并没有利用当前的网络技术,软件本身也不是一个精干的数据存储而是因业务相关的特性而臃肿([
PLL09 ])。

     比如Lotus Notes。商业分析或面向流处理的数据存储显示,这类关系数据库的替代品已经存在了非常长的时间。博主Dennis Forbes因此批评,“一刀切”的说法仅仅只是是一些人的挡箭牌,由于他们仅仅使用过RDBMS作为处理全部的结构化和非结构化数据存储需求的工具([ For10 ])。

2.2.4 NoSQL代表全然的“没有SQL”
     首先,非常多NoSQL的主张特别是在博客上的。将这个术语和潮流看作RDBMS的全然否定和这些系统的死亡宣告。“NoSQL”术语通常与Eric Evans联系在一起,尽管他不是第一个用它(见2.1节,如[ Ell09a ])。2009年的一篇博客觉得。如今这个词的意思是“不应仅仅有SQL(Not Only SQL)”而不是“没有SQL”([ Eva09b ])。这个词已经被很多博客作者所採纳。由于它强调了数据库中的持久性不意味着仅仅能使用RDBMS而是有替代品存在。

博主Nati
Shalom评论例如以下:“我觉得我们所示是很多其它的一种现实,现有的SQL数据库方案可能不会非常快消失,但同一时候他们不能解决世界上全部的问题。

有趣的是,NoSQL这个词已经变为Not Only SQL,以代表这一思路”([ Sha09a ])。一些博主强调这个词语不精确。如Dare Obasanjo说,“还没有什么产品是‘NoSQL’数据库的确切技术定义,当其实它不是一个关系数据库”([ Oba09a ])。其它人。如Michael Stonebraker声称。根本和SQL没半毛钱关系,应该叫“NoACID”之类,这是由Dennis
Forbes提出的并在他的建议里引用了Stonebraker([ For10 ])。另一些人如Adam Keys批评术语“NoSQL”仅仅定义了它不代表什么趋势([ Key09 ]):“这个名字的问题是,它仅仅定义了它不是什么。这使得它是对抗性的,它所包括或排除的东西不令人吃惊。我们看到的是,它终结了有价值的数据应该保存在某种关系数据库的如果。终结了SQL和ACID是解决我们问题的唯一工具的如果。终结了主/从模式的活力;终结了在我们的应用程序代码里编织关系模式”。他建议把这样的潮流和数据存储归入“后关系型”而不是“NoSQL”:“我们看到关于应怎样存储关键数据的思维爆炸;我们审视数据来看是否值得持久化;我们尝试新的语义结构、一致性和并发性。如同后现代主义是反思过去的艺术和建筑的方式,后关系型是软件开发商又一次考虑自己方式的一个机会。正如后现代主义并非否能定整个艺术史,后关系型不会终结关系数据库的有用性。”([
Key09 ])。然而。像他博客的读者评论的,这个词并不比“NoSQL”更好,由于它仍仅仅是定义这个潮流和这种数据库不反映(或更好的:他们所省略)的东西。而不是它们主张什么。

     对这个词的刺激和作为关系数据库的忽视部分的第一观念,已经带来了NoSQL支持者们很多发人深省的语句。并造成一些无益的讨论和一些激烈争论(比如[ Dzi10 ]和它的响应[ Sch10 ])。

2.2.5 Stonebraker对NoSQL数据库的关键观点
     在他的博文“‘NoSQL’讨论与SQL无关”([Sto09])中,Michael Stonebraker说最近已有大量对NoSQL数据库的讨论。在他的观点里美国的NoSQL研讨背后的驱动力是文档存储和键/值存储的倡导者,在他眼中它们提供“低层、一次一条记录的DBMS接口。以代替SQL”。Stonebraker看到两个走向非关系数据存储的原因——灵活性和性能。

     灵活性的争论  Stonebraker未进一步研究,但它包括下列观点:可能有这种数据。其不符合刚性的关系模型,且和RDBMS的结构紧密绑定。对于这种数据更灵活是必要的。
     性能的争论  Stonebraker描写叙述例如以下:起先使用MySQL存储数据但性能随时间下降。

这导致了下面选择:要么在应用程序中对多个网站上的数据碎片/分区导致“管理分布式数据的严重问题”。或从MySQL走向商业RDBMS可引起大的许可费;或甚至全然放弃RDBMS。

     Stonebraker在他的博客中研究了后者。他针对“NoSQL数据库最通常考虑的负载:更新和查询密集型的OLTP负载,不是查询密集型的数据仓库负载”,或专业的负载如文档知识库。
     Stonebraker看到两个选项提高OLTP事务的性能:
     1、“无共享处理环境”上的自己主动分片实现的水平缩放。在这样的情况下。性能因添加新的节点得到改善。在他看来。在过去的十年里写的RDBMS提供了“无共享的架构”。“没有人应该执行不提供这个功能的DBMS”。

     2、单点OLTP性能的改进
    Stonebraker集中在第二项,分析减少单点OLTP事务性能开销的来源;他的博客文章的标题表明。这些都和查询语言(SQL)无关。他说,仅仅有一小部分的事务消耗是由实用的工作引起的。并看到五个性能开销的来源,单节点性能应优化应据此进行:
     通信  应用和DBMS间通过ODBC或JDBC进行的通信。这被觉得是OLTP事务开销的主要来源,通常例如以下描写叙述:“基本上全部性能敏感的应用程序使用存储过程接口来执行DBMS内的应用程序逻辑。避免了应用与DBMS之间来回通信的沉重的开销”。

为了降低通信开销的还有一个选择是使用一个嵌入式DBMS。指的是应用程序和DBMS在同一地址空间中执行;由于强耦合。安全性和訪问控制问题对“安全是一个大问题的主流OLTP”没有可行的替代。Stonebrakers觉得。

     日志  每一个事务除改动关系型数据外由DBMS负责记录日志。

因为日志文件被保存到磁盘以确保持久性,日志是昂贵的且会减少事务性能。

     加锁  数据集的加锁操作会导致开销,由于加锁表的写操作仅仅能在事务改动操作之前或之后才干发生。
     闩锁  由于RDBMS中共享的数据结构(如B树、锁表、资源表)进一步添加事务开销。

这些数据结构都是由多个线程訪问短期锁(称为闩锁)通经常使用于提供并行的但慎重的訪问。

     缓存管理  当讨论事务开销时缓存管理也有其责任。因传统RDBMS中的数据以固定页的方式组织。必须管理内存中的磁盘页面缓存(通过缓冲池完毕)。并解决数据库条目写到磁盘页(和返回)以及识别字段边界的问题。

     如前所述。依据Stonebraker,通信是开销的主要来源,并远超过其它的项目(从这个调查:[ HAMS08 ]),其它项目近似相等地添加总事务成本。除了避免应用程序和数据库之间的通信,其它四个性能开销的来源必须消除。以大大提高单节点性能。

     如今。不管是否是关系型的数据存储通常都有特定的主题。NoSQL数据库也须要找出上述性能开销的组成部分。在这种背景下,Stonebraker提出以下的样例:
  • 在多个网站之间数据分布且无共享的方法在关系型以及非关系型数据存储中都提供了。

    “显然,一个精心设计的多网站系统。不管是否基于SQL或其它,都比单网站系统更具可扩展性”,据Stonebraker说。

  • 很多NoSQL数据库是基于磁盘的。实现一个缓冲池和多线程。当提供这些特性和性能时,四个性能开销来源中的两个仍然存在(锁定。缓存管理)。不能被消除。
  • 非常多智能事务的NoSQL数据存储仅仅提供带BASE属性(见第3章)的单记录事务。与关系型DBMS相反,ACID属性为性能而牺牲。
     于是Stonebraker总结他的观点例如以下:“然而。一个NoSQL、基于磁盘、非ACID、多线程系统的单节点性能被限制为比设计良好的存储过程SQL的OLTP引擎略快。 本质上,ACID事务因适度的性能提升而被抛弃,且这种性能提升与SQL无关”。

在他的观点中,加速DBMS的实际任务集中于消除加锁、闩锁、日志和缓冲区管理。以及支持存储过程从高级语言(如SQL)编译为低级语言。这种系统的样子在论文“架构时代的终结:是全然重写的时候了”([SMA+07])中被阐述并已经在上文讨论了。

     Stonebraker也不指望 SQL数据存储的死,而是说:“我全然期待快速度的、开源的SQL引擎在不久的将来提供自己主动分片。此外,他们将继续提供ACID事务以提高程序猿的工作效率,减少维护成本,以及由SQL支持的更好的数据独立性”。因此“高性能不须要抛弃SQL或ACID事务”。这也“取决于消除由传统的ACID事务、多线程管理、磁盘管理带来的开销”。消除这些开销的来源“在SQL上下文或其它上下文环境中都是可能的”。Stonebraker总结。

2.2.6 运维和操作人员的需求
     Schmidt在他的博客“NoSQL”的黑暗面([ Sch09 ])中觉得,NoSQL的辩论被开发人员的观点主宰。其通常反复着开发人员喜欢的特性和能力(如性能、用途、无模式、好的API),而操作人员和系统管理员的需求通常被遗忘在他的视线中。他报道了一些公司遇到困难特别是在下面领域:
     即席数据修复  要同意对即席数据修复。首先必须有某种查询和操作语言。其次,在分布式数据库(如Project Voldemort和Cassandra)中更难以修复数据,与在一个节点上执行或有专门分片的数据存储相比。
     即席数据查询  与数据修复相似。当遇到即席查询时针对特定数据存储的查询和操作是必须的,和查询集中式存储相比查询分布式数据存储更难。

Schmidt指出,对一些报表任务来说MapReduce方法([ DG04 ])是合适的,但不是对每个即席查询。此外,他看到的是文化而不是技术问题。客户已经被培训和“上瘾”使用即席查询。因而不喜欢这些手段的缺失。针对详尽报表的需求。Schmidt建议使用镜像了线上库的关系型数据库,而线上库可能由于性能和可扩展性要求而使用NoSQL存储。

     数据导出  Schmidt指出,这方面NoSQL数据库之间有巨大差异。一些提供了实用的API来訪问全部的数据。还有一些中则不存在。他也指出。从非分布式NoSQL存储像CouchDB,MongoDB或Tokyo Tyant中导出数据,要比从分布式的如Project Voldemort或Cassandra中导出数据更easy。

     Schmidt的观点在讨论“你的NoSQL指南”([ Ake09 ])中被幽默和广泛地反复。特别是恶搞了NoSQL支持者的用MapReduce风格处理每一个查询需求的论点。

2.2.7 性能 vs. 可扩展性
     BJ Clark介绍了一个在各种NoSQL数据库和MySQL间的性能和可扩展性实验。发表在他的博客“NoSQL:假设它是那么easy”。首先,他定义可扩展性为“在保持比例的前提下改变大小,在计算机学科中这通常意味着添加吞吐量。”博主Dennis Forbes允许这一可扩展性的概念,“务实地衡量一个解决方式的能力,其以可实现的方式增长到一个最高的现实水平。同一时候保持可接受的服务水平”([ For10
])。

BJ Clark继续说:“扩展不是:性能。在现实中,扩展和变快没有什么关系。它仅仅与大小有关。如今。扩展和性能典型地如此联系到一起,假设什么是高效的,它实际上可能不须要扩展。”([ Cla09 ])。

     对于关系数据库Clark指出:“RDBMS的问题不是他们不扩展,是他们非常难以规模。

分片是最明显的扩展方式,但分片多个能訪问随意列的表会非常快使人崩溃。”博主Dennis Forbes允许他。“有一些老派的关系数据库确实有扩展性问题”([ For10 ]),但使用如Adam Wiggins的技术还是有可能让它们扩展的([ Wig09 ])。

     除了关系数据库的分片和典型错误的回避(如死板的规格化和不良索引导致的昂贵的连接),Forbes觉得垂直缩放仍然是一种选择,它非常easy且计算上有效,且能远远率先于“成队的强力核心,数百GB的内存,在成堆的SSD组成的SAN阵列上操作”。缺点是,Forbes也承认垂直缩放相对昂贵。

但Forbes也主张关系数据库通过数据分区和将每台机器增加失败恢复集群实现的水平缩放。以达到冗余和可用性。考虑到约束非常少且钱通常不是问题的大公司的部署情况。他以自己的经验说,“这样的扩展存在于差点儿全部的银行、交易系统、能源平台、零售系统等等。要声称SQL系统不能扩展,是对这样明显的证据的蔑视,无视全部的理由”([
For10 ])。Forbes主张使用自己的server。由于他看到一些云计算环境的人为限制,如单一实例的Amazon EC2的IO限制和相对高费用;他觉得“这些金融和人为限制解释了对同意你螺旋上升的技术的强烈兴趣”([ For10 ])。

     BJ Clark在他的博客上发表对一些NoSQL数据存储的评价,该评价关注于自己主动可扩展性(比如通过自己主动分片),由于他须要更新数百万个对象(他称他们为主要对象)与其它对象(他称他们为辅助对象)是1:1或1:N的依赖关系。辅助对象大多是在表的结尾处插入。

     他的评价能够概括例如以下:
  • 键/值对存储Tokyo Tyant/Cabinet和Redis不提供自己主动水平伸缩的特性。假设加入机器——类似memcached——必须让应用知道。然后在数据库server群中对数据库条目(重)哈希,以利用额外的资源。还有一方面他指出,Tokyo Tyant/Cabinet和Redis的表现非常好,横向扩展的须要不会非常早出现。

  • 分布式键/值存储Project Voldemort自己主动地利用新加入集群的server并提供故障容错。鉴于它专注于分片和故障容错且有一个可插拔的存储架构,Tokyo Tyant/Cabinet或Redis能够作为Voldemort的存储后端。假设这些系统须要扩展的话,这也是一个可能的迁移路径。
  • 文档数据库MongoDB表现出良好的性能特点。但在评价时没有自己主动缩放能力,由于它没有提供自己主动分片(在2010年8月的1.6版中已经改变,參见[ Mon10 ]和[ MHC+10b ])。

  • 对于列数据库Cassandra,Clark觉得它是“绝相应该,且可能在Facebook,是通过简单地加入还有一台机器来扩展的(节点间互相挂钩使用Gossip协议),但OSS版本号不支持一些关键的东西,像一起释放一台机器“。

    这一结论反映了Cassandra评价时的发展状况。

  • Amazon的键/值对存储S3扩展良好。但据Clark说,它不如其它候选者那样高性能。

  • MySQL,相比較而言,并不提供自己主动横向扩展如自己主动分片,但Clark指出。对于大多数应用(甚至是Web应用如Friendfeed,參见[ Tay09 ])MySQL足够快。而且是“熟悉的、无处不在的”。

    与Tokyo Tyant/Cabinet和Redis相比,Clark觉得“它能够做Tokyo Tyant和Redis能够做的一切。且真的是没有那么慢。其实,对于某些数据集。我见过MySQL比Tokyo Tyant运行地快得多”和“对MySQL分片与Tokyo
    Tyant和Redis一样easy甚至更easy,非常难说他们能够在更多问题上赢得胜利。”

     在上述评价中所提到的系统将在本文中更具体地讨论。

此外必须提到的是,评估发生在2009的夏天(博客是8月发表),因此,结果反映了被评价系统在那个时候的发展状态。

     Clark总结了他的研究结果。在他看来RDBMS不比“其他非常多东西”更难扩展,NoSQL数据库提供的仅有的一些手段有是自己主动的、水平可扩展性、同意不须要操作员交互下加入机器。

因此。甚至能够觉得“扩展MySQL(通过MySQL Proxy来分片)和为这些NoSQL数据库做分片相同easy。”因此他没有宣布RDBMS早早死亡。提醒道MySQL仍然是在大站点如Facebook,Wikipedia和FriendFeed中使用。他建议新的应用程序使用最适合工作的工具,反映了非关系型数据库——就像关系型的一样——没有“一刀切”的解决方式:

     “假设我须要报表,我不会使用不论什么NoSQL。假设我须要缓存,我非常可能会使用Tokyo Tyant。

假设我须要ACID特性,我不会使用NoSQL。假设我须要一吨值对,我会使用Redis。假设我须要事务,我会使用Postgres。假设我有一吨单一类型的文件,我可能会使用Mongo。假设我须要每天写10亿个对象,我可能会使用Voldemort。假设我须要全文搜索。我可能会使用Solr。

假设我须要易变数据的全文搜索,我可能会使用Sphinx。”


2.2.8 不是全部RDBMS表现得像MySQL
     NoSQL的辩论中常常发现的争议是RDBMS非常难良好扩展且非常难分片。这一般是通过MySQL的样例指出。

此外,NoSQL数据库有时被看作MySQL加memcached方案的继任者(比如[ Hof10c ]),后者将负载从数据库带走以降低和延缓分布式的需求。关于这些典型争论博主Dennis Forbes提醒。不easy区分一般的RDBMS和MySQL,其他数据库可能更easy或更好地扩展:“MySQL不是RDBMS世界的先锋。它在高负载站点下的问题和关注非常少与其他数据库系统相关”([
For10 ])。


2.2.9 批评的误解
     NoSQL倡导者Ben Scofield回答了一些上面提到的批评。他觉得是被误解了。他在NoSQL争论中表达的一些精辟论点回答了这些批评([ Sco09 ]):
     “NoSQL仅仅是可扩展性和/或性能。”  Scofield觉得,这对那些“传统主义者”(他这样称呼他们)可能是一个有吸引力的观点,觉得仅仅要让RDBMS更快和更具可扩展性就能使NoSQL数据存储过时。他声称“NoSQL除了性能和扩展外还有很多其它”,比如“NoSQL数据库通常为业务域建模提供更好的基础”。
     “NoSQL仅仅是文档数据库。或键值存储,或……”  Scofield指出。很多NoSQL文章仅仅介绍面向文件的数据库或键值存储。有时提到列存储。

他指出“对特定情况下的每个解决方式都能够提出好的讨论,但上述那些仅仅是讨论某一特定类型的存储引擎。”Scofield因此批评,将讨论范围缩小到仅仅有一类NoSQL数据库,会使得传统主义者非常easy地否定整个潮流或全套不同的NoSQL方法。

     “我在NoSQL能做的在关系数据库中一样能。

”  考虑到Friendfeed使用MySQL的频繁争论([ Tay09 ])。Scofield指出,虽然微调一个关系型数据库是可能的。但这对全部类型的数据没有意义。“不同的应用适合不同的事情。关系数据库对关系数据是伟大的,但对非关系数据为什么要使用他们?”他问道。

     “NoSQL是一个关系数据库的广泛排斥。”  前一段时间这样的说法在NoSQL社区常常被听到,后来成了不常见的。Scofield观赏:“看来我们正在走向一个多元化的方法来储存我们的数据,这是一件好事。我已经为这样的做法提出了’多语言持久化’(尽管我没有杜撰一个术语)。但我也喜欢如Ezra Zygmuntowicz的’LessSQL'作为标签。”


2.3 NoSQL数据库的分类和比較
     在过去的几年里。各种NoSQL数据库主要由从业人员和网络公司开发,以满足他们对可扩展性的性能、维护和功能集的详细需求。

已经透露的是这些数据库中的一些借鉴了Amazon的Dynamo([DHJ+07 ])或Google的Bigtable([ CDG+06 ])或两者的思想。

其它一些移植了针对现代网络技术开发的现有数据库的思想如CouchDB。另一些人追求全然不同的方案如Neo4j或HypergraphDB。

     由于各种不同的方法、重叠的非功能性需求、不同的功能集。可能非常难获得和维护一个非关系型数据库情况的概述。所以有各种不同的方法对NoSQL数据库分门别类,每种都有不同的类别和子类别。这里介绍一些分类方法。应当用哪一个对NoSQL数据存储分类将在兴许的章节介绍。

2.3.1 按数据模型的分类法
     关于NoSQL存储伸缩性的分类法,作者Todd Hoff引用了一个Stephen Yen在他的博文“NoSQL分类法的赞同”中的演示文稿([ Hof09c ])。在演示文稿“NoSQL是一个没有马的马车”([ Yen09 ])中Yen建议的分类法能够在表2.1中找到。
词汇 符合的数据库
Key-Value-Cache
Memcached
Repcached
Coherence
Infinispan
EXtreme Scale
Jboss Cache
Velocity
Terracoqa
Key-Value-Store
keyspace
Flare
Schema Free
RAMCloud
Eventually-Consistent Key-Value-
Store
Dynamo
Voldemort
Dynomite
SubRecord
Mo8onDb
Dovetaildb
Ordered-Key-Value-Store
Tokyo Tyrant
Lightcloud
NMDB
Luxio
MemcacheDB
Actord
Data-Structures Server
Redis
Tuple Store
Gigaspaces
Coord
Apache River
Object Database
ZopeDB
DB4O
Shoal
Document Store
CouchDB
Mongo
Jackrabbit
XML Databases
ThruDB
CloudKit
Perservere
Riak Basho
Scalaris
Wide Columnar Store
Bigtable
Hbase
Cassandra
Hypertable
KAI
OpenNeptune
Qbase
KDI
表2.1:分类——Stephen Yen的NoSQL分类法([Yen09])

     一个类似的分类法,比上面的分类法更粗粒度和易理解。能够在文章“云数据库”([ Nor09 ])中找到。

表2.2总结了他的数据仓库分类,另外包含一些仅仅在云计算环境中可用的数据存储。

归类
符合的数据库
Distributed Hash Table, Key-Value Data Stores
memcached
MemcacheDB
Project Voldemort
Scalaris
Tokyo Cabinet
Entity-Attribute-Value Datastores
Amazon SimpleDB
Google AppEngine datastore
Microsoft SQL Data Services
Google Bigtable
Hadoop
HyperTable
HBase
Amazon Platform
Amazon SimpleDB
Document Stores, Column Stores
Sybase IQ
Vertica Analytic Database
Apache CouchDB
表2.2:分类——Ken North的归类([Nor09])

     与上面的分类法类似。Rick Cattel主要按数据模型将不同的NoSQL数据库分类。见表2.3。
归类 符合的数据库
Key-value Stores
Redis
Scalaris
Tokyo Tyrant
Voldemort
Riak
Document Stores
SimpleDB
CouchDB
MongoDB
Terrastore
Extensible Record Stores
Bigtable
HBase
HyperTable
Cassandra
表2.3:分类——Rick Cattel的归类([Cat10])

2.3.2 Ben Scofield的归类
     博主Alex Popescu总结了由Ben Scofield给出的一份演示文稿。该文稿给出了NoSQL数据库一个通用的带分类法的介绍,以及不同NoSQL数据库的Ruby样例([ Sco10 ])。

这一分类法实际上是一个简短的NoSQL数据库非功能类型(“称为ities”)的比較,外加功能覆盖率的评分。

Popescu总结了Scofield的思想。如表2.4。



性能
扩展性
灵活性
复杂性
功能性
Key-Value Stores
high
high
high
none
variable (none)
Column stores
high
high
moderate
low
minimal
Document stores
high
variable (high)
high
low
variable (low)
Graph databases
variable
variable
high
high
graph theory
Relational databases
variable
variable
low
moderate
relational algebra
表2.4:分类——Scofield和Popescu的分类法及比較([Pop10b], [Sco10])

2.3.3 可扩展性、数据和查询模型、持久化设计的比較
     在博客“NoSQL生态系统”中Jonathan Ellis讨论了NoSQL数据存储的三个重要方面:
     1、可扩展性
     2、数据和查询模型
     3、持久化设计

可扩展性

     Ellis觉得,通过数据副本和这些副本上的负载分布非常easy实现读操作的可扩展。

因此,他仅仅研究真正分布式和提供自己主动数据分区的数据库的写操作扩展。

当数据大小超过单一机器的能力时,假设不愿意手动分区的话后者系统似乎是他唯一的选择(这不是一个好主意,依据[
Oba09b ])。对于相关的提供自己主动分片的分布式系统,Ellis看到两个重要特点:

  • 支持多数据中心
  • 加入机器到现有群集的可能性,对使用该群集的应用程序透明
     依据这些特点Ellis比較了一些实现这些要求的真分布式和自己主动分片的NoSQL数据库(參见表2.5)。

数据存储
在线加入机器
多数据中心支持
Cassandra
X
X
HBase
X

Riak
X

Scalaris
X

Voldemort

Some code required
表2.5:分类——扩展性对照([Ell09a])

     下面的NoSQL存储已被排除在这样的比較外,由于他们在分布式上不满足Ellis的要求(在2009年11月他公布博客的时间):CouchDB。MongoDB。Neo4j,Redis和Tokyo Cabinet。然而据他说,这些系统能够作为一个分布式系统的持久层使用。文档数据库MongoDB和CouchDB支持有限的自己主动分片,在他调查的时间(MongoDB开箱,CouchDB通过划分/聚类框架Lounge)。关于Tokyo
Cabinet,Ellis说它能够用作Project Voldemort的存储后端。

数据和查询模型

     Ellis研究的第二个领域是数据模型和不同的NoSQL存储提供的查询API。

表2.6显示了他的调查结果,指出了各种数据模型和查询APIs的巨大区别。


数据存储
数据模型
查询API
Cassandra
Columnfamily
Thrift
CouchDB
Document
map/reduce views
HBase
Columnfamily
Thrift, REST
MongoDB
Document
Cursor
Neo4j
Graph
Graph
Redis
Collection
Collection
Riak
Document
Nested hashes
Scalaris
Key/value
get/put
Tokyo Cabinet
Key/value
get/put
Voldemort
Key/value
get/put
表2.6:分类——数据模型和查询API的比較([Ell09a])

     Ellis对这些系统的数据模型和查询API进行了下面评论:
  • Columnfamily模型,由Cassandra和HBase实现,是由Google的Bigtable论文第二节的相关段落得到启示([ CDG+06,2页])。Cassandra与HBase相反省略了历史版本号,引入了超列的进一步概念。在Cassandra和HBase里列是稀疏的,这意味着他们可能有不同数量的单元。且列不必预先定义。

  • 键/值模型是最easy实现的,但可能是低效的,假设一个人仅仅对请求或更新与某个键相关的部分值感兴趣。此外。在键/值存储上非常难构建复杂的数据结构(正如Ellis在还有一篇博客中描写叙述的。參见[ Ell09b ])。
  • Ellis将文档数据库看做是键/值存储的下一步,由于它们同意嵌套的值。他们同意比键/值存储更效率地查询数据结构,由于当他们请求一个键时不须要返回整个BLOB值。
  • 图数据库Neo4j具有独特的数据模型。因对象及其关系被作为一个图的节点和边来建模和持久化。适合此模型的查询可能比其他数据存储上同样的查询快三个数量级(由Emil Eifrem。Neo4j背后公司的首席运行官,參见[ Eif09 ])。
  • Scalaris在所评价的键/值存储中是独一无二的,由于它同意多个键上的分布式事务。

持久化设计
     Ellis对照他所选的NoSQL数据存储的第三方面,是他们储存数据的方式(见表2.7)。


数据存储
持久化设计
Cassandra
Memtable / SSTable
CouchDB
Append-only B-tree
HBase
Memtable / SSTable on HDFS
MongoDB
B-tree
Neo4j
On-disk linked lists
Redis
In-memory with background snapshots
Riak
?
Scalaris
In-memory only
Tokyo Cabinet
Hash or B-tree
Voldemort
Pluggable (primarily BDB MySQL)
表2.7:分类——持久化设计的比較([Ell09a])

     Ellis觉得持久化设计对预计何种负载下这些数据库会表现得好是特别重要的:
     内存数据库很快(如Redis可在单机达到每秒100000次操作),但数据的大小天生的受RAM限制大小。还有一个缺点是耐久性可能成为一个问题,由于潜在地大量数据可能在两次磁盘写中间丢失(比如由于server崩溃或掉电)。

Scalaris通过复制解决问题——但它不支持多个数据中心——掉电的威胁依旧存在。

     内存表和SSTables以例如以下方式工作:在写入一个仅仅能追加的提交日志以确保耐久性后,写操作在内存中缓存(在内存表内)。经过一定数量的写,内存表作为一个总体被刷新到磁盘(这时被称为SSTable;这些想法都来自Google的Bigtable论文,參见[ CDG+06,5.3和5.4节 ])。

这一持久化策略具有与内存数据库相媲美的性能特点(由于——与基于磁盘的策略相比——由于追加日志和将整个内存表写回磁盘减小了寻道时间),且避免了纯内存数据库的耐久性问题。

     B树由于能提供一个强大的索引支持已在数据库中使用。他们在磁盘上的性能特性不是非常正面,原因是读写操作所需的大量寻道。文档数据库CouchDB内部使用B树。但通过仅仅追加到B树试图避免寻道的开销,这意味着一次仅仅能有一个写操作的缺点,由于这样的情况下并发读B树的不同段是不同意的。


基于用户须要的分类法

     Todd Hoff([Hof09b])引用博主James Hamilton提供了一种不同的划分NoSQL数据库的方法([Ham09]),依据用户需求划分数据库:
     特性第一  这一类的数据库提供了一个(大)量的高层次的特性。使程序猿的工作更easy。不足之处是他们非常难扩展。样例包含:Oracle,Microsoft SQL Server,IBM DB2,MySQL,PostgreSQL,Amazon RDS。

     扩展第一  这样的类型的数据库从一開始就须要扩展。

不足之处是,他们缺乏特定的特性且把责任还给程序猿。样例包含:Project Voldemort,Ringo。Amazon SimpleDB,Kai,Dynamite,Yahoo PNUTS,ThruDB。Hypertable,CouchDB。Cassandra,MemcacheDB。

     简单结构存储  这个类包括键/值对存储。强调存储和检索随意结构的集合。依据Hamilton他们的缺点是“通常不具有其它系统的功能或可扩展性”。

样例包括:文件系统,Cassandra,BerkelyDB。Amazon SimpleDB。

     特定目的优化的存储  这些数据库被设计和建造以擅长做一件事,如数据仓库或流处理。这种数据库的样例有:StreamBase。Vertica,VoltDB。Aster Data。Netezza,Greenplum。

     Hamilton和Hoff觉得。这样的分类法对将一类数据库和特定用例匹配是实用的。尽管这样的分类是不完整的。如不包括图数据库,且怎样符合上述四类是不明白的。

此外。重要的是要注意。一些数据库能够在不同的类中找到(Cassandra。SimpleDB),因此这样的分类不提供一个确定的差别使每一个数据库仅仅归入一个类(这——在作者看来——在NoSQL数据库领域即使不是不可能至少也非常困难)。


2.3.4 本文的分类法
     考虑基本概念和下一章中的NoSQL数据库技术后。接下去的章节将研究各种类别的非关系型数据存储。并审视特定的产品。

这些产品以他们的数据结构来分类。追随上面所提到的Yen,North和Cattell的分类法(參见2.3.1),这也被本文的其它多数资料来源共享。在这篇文章中使用的分类是:键/值存储、文档数据库和面向列的数据库。

NoSQL数据库介绍(2)的更多相关文章

  1. NoSQL数据库介绍

    NoSQL在2010年风生水起,大大小小的Web站点在追求高性能高可靠性方面,不由自主都选择了NoSQL技术作为优先考虑的方面.今年伊始,InfoQ中文站有幸邀请到凤凰网的孙立先生,为大家分享他之于N ...

  2. [转载]12款免费与开源的NoSQL数据库介绍

    Naresh Kumar是位软件工程师与热情的博主,对于编程与新事物拥有极大的兴趣,非常乐于与其他开发者和程序员分享技术上的研究成果.近日,Naresh撰文谈到了12款知名的免费.开源NoSQL数据库 ...

  3. NoSQL数据库介绍(4)

    4 键/值存储      讨论了经常使用的概念.技术和模式后.第一类NoSQL数据存储会在本章进行研究. 键/值存储通常有一个简单的数据模型:一个map/dictionary,同意客户按键来存放和请求 ...

  4. NoSQL数据库的认识

    SQL数据库和NoSQL数据库介绍 什么是SQL数据库? 关系型数据库是依据关系模型来创建的数据库.而所谓的关系模型就是“一对一.一对多.多对多”等关系模型,这是一种二维表格模型,因此一个关系型数据库 ...

  5. noSQL数据库相关软件介绍(大数据存储时候,必须使用)

    目前图数据库软件七种较为流行:Neo4J, Infinite Graph, DEX,InfoGrid, HyperGraphDB, Trinity, AllegroGraph(http://tech. ...

  6. nosql的介绍以及和关系型数据库的区别

    一直对非关系型数据库和关系型数据库的了解感觉不太深入,在网上收集了一些关于sql和nosql的区别和优缺点分享给大家. Nosql介绍 Nosql的全称是Not Only Sql,这个概念早起就有人提 ...

  7. 161104、NoSQL数据库:key/value型之levelDB介绍及java实现

    简介:Leveldb是一个google实现的非常高效的kv数据库,能够支持billion级别的数据量了. 在这个数量级别下还有着非常高的性能,主要归功于它的良好的设计.特别是LSM算法.LevelDB ...

  8. 非关系型数据库(nosql)介绍

    非关系型数据库也叫Nosql数据库,全称是not noly sql. 2009年初,Johan Oskarsson举办了一场关于开源分布式数据库的讨论,Eric Evans在这次讨论中提出了NoSQL ...

  9. 几款主流 NoSql 数据库的对比

    最近小组准备启动一个 node 开源项目,从前端亲和力.大数据下的IO性能.可扩展性几点入手挑选了 NoSql 数据库,但具体使用哪一款产品还需要做一次选型. 我们最终把选项范围缩窄在 HBase.R ...

随机推荐

  1. Loj#6432「PKUSC2018」真实排名(二分查找+组合数)

    题面 Loj 题解 普通的暴力是直接枚举改或者不改,最后在判断最后对哪些点有贡献. 而这种方法是很难优化的.所以考虑在排序之后线性处理.首先先假设没有重复的元素 struct Node { int p ...

  2. JavaScript中的Date类型

    ECMAScript中的Date类型是在早起Java中的java.util.Date类基础上构建的.为此,Date类型使用自UTC(Coordinated Universal Time,国际协调时间) ...

  3. 手机发送验证码—.net代码

    注册过程中,短信发送验证码流程如下: (1).用户提交手机号码,申请湖区验证码 (2).网站按照预制规则生成验证码 (3).网站将用户手机号码和验证码发送到短信平台 (4).将制定内容发送到制定手机号 ...

  4. Codeforces 980 E. The Number Games

    \(>Codeforces \space 980 E. The Number Games<\) 题目大意 : 有一棵点数为 \(n\) 的数,第 \(i\) 个点的点权是 \(2^i\) ...

  5. 【推导】【贪心】XVII Open Cup named after E.V. Pankratiev Stage 14, Grand Prix of Tatarstan, Sunday, April 2, 2017 Problem D. Clones and Treasures

    给你一行房间,有的是隐身药水,有的是守卫,有的是金币. 你可以任选起点,向右走,每经过一个药水或金币就拿走,每经过一个守卫必须消耗1个药水,问你最多得几个金币. 药水看成左括号,守卫看成右括号, 就从 ...

  6. [JZOJ3484]密码

    题目大意: 给你一个很长的字符串a(|a|<=300000),一个比较短的字符串b(|b|<=200),请你搞一些破坏. 你可以从a的两边去掉一些字符使得b仍是a的一个字串,问有多少种方案 ...

  7. Problem C: 零起点学算法93——矩阵转置

    #include<stdio.h> int main() { ][],b[][]; while(scanf("%d%d",&n,&m)!=EOF) { ...

  8. window下命令行的方式安装svn服务端

    下载Binary Packages类型的 安装文件  https://www.visualsvn.com/server/download/  自己选择版本 第一步 :开始安装到 c:/software ...

  9. Mac电脑,Andorid studio 配置 Flutter

    1,下载flutter cd ~/Library/ git clone -b dev https://github.com/flutter/flutter.git 2,环境配置: 这里配置用户级别环境 ...

  10. 为什么控制台console.log一个值,总是会多一个undefined

    我们发现在浏览器控制台打印东西的时候,末尾总是会莫名其妙多出一个undefined? 这是为什么呢? 大胆猜测一下,应该执行的函数没有返回值,而浏览器默认要打印出执行函数的返回值,才会打印undefi ...