3.4 NoSQL数据库的分类
按照功能和属性,NoSQL数据库可分为面向列的有序存储数据库、键/值存储数据库、面向文档数据库、图形数据库和对象数据库5类。
3.4.1 面向列的有序存储数据库
面向列的有序存储数据库,它将数据表存储为数据列而非行的形式。从物理上来说,表是列的集合,每一列从本质上来说都是只有一个列的表。面向列的存储能够高效地存储数据,如果列值不存在就不用存储,即遇到“NULL”值时不用存储也就有效地避免了浪费存储空间。每个数据单元可以看作一组键/值对集合,数据单元本身通过主标识符(primary identifier)标识,主标识符又称为主键(primary key)。数据单元按照主键的值进行排序,数据单元里面可以包含任意数量的列,并且列可以动态加入和删除,不需要创建表的时候预定义列。面向列的NoSQL包括Google BigTable、HBase、Hypertable和Cloudata,以及国产、自主可控的南大通用GBase 8a等。
面向列的有序存储数据库通常用于分析系统、商业智能与分析型数据存储。它具有以下优点:
(1)可以比较数据,因为在表的一列中数据通常都是同种类型的。
(2)可以通过便宜、性能一般的硬件实现高速的查询性能,由于压缩的原因,相对于关系型数据库来说,这种方式的磁盘上的数据所占的空间要少很多。
面向列的有序存储数据库具有以下缺点:
(1)通常没有事务。
(2)对于熟悉传统关系型数据库管理系统的开发者来说存在不少限制。
面向列的有序存储数据库适用的场景:
(1)事件记录:由于列族数据库可存放任意数据结构,所以它很适合用来保存应用程序状态或运行中遇到的错误等事件信息。在企业级环境下,所有应用程序都可以把事件写入Cassandra或者GBase数据库。它们可以用appname: tirnestarnp(应用程序名:时间戳)作为行键,并使用自己需要的列。由于列族数据库的写入能力可扩展,所以在事件记录系统中使用它效果会很好。
(2)内容管理系统与博客平台:使用列族可以把博文的“标签”(tag)、“类别”(category)、“链接”(link)和“trackback”等属性放在不同的列中。评论信息既可以与上述内容放在同一行,也可以移到另一个“键空间”。同理,博客用户与实际博文也可存于不同列族中。
(3)计数器:在网络应用程序中,通常要统计某页面的访问人数并对其分类,以便为计算和分析数据所使用。
(4)限期使用:有些时候,企业需要向用户提供试用版,或是在网站上将某个广告条显示一定的时间,这些功能可以通过“带过期时限的列”(expiring olumn)来完成。这种列过了给定时限后,就会由Cassandra自动删除。这个时限称为TTL(Tirne To Live,生存时间),以秒为单位。经过TTL指定的时长后,这种列就被删掉了。程序若检测到此列不存在,则可收回用户访问权限或移除广告条。
3.4.2 键/值存储数据库
键/值存储可以将键/值对存储到持久化存储中,随后使用键来读取值。键/值对结构较为简单,如哈希表或关联数组。键/值对的键/值在集合中唯一,易于查找,由于没有SQL处理器、索引系统以及分析系统等诸多限制,所以在数据访问操作时效率很高。这种解决方案提供了最高效的性能、代价最低的实现以及可伸缩性。键/值存储数据库的结构就是采用键/值对结构。键/值存储各不相同,有些把数据保存在内存中,有些把数据持久化到磁盘里面,有些作为缓存进行存储。NoSQL中的键/值存储有些以Oracle的Berkeley DB作为底层存储,核心存储引擎并不关注键或值的含义,只管保存传入的字节数组对,然后返回同样的数据给调用客户端。Berkeley DB支持将数据缓存在内存中,随数据增长将其刷新到磁盘。它还支持对键索引,帮助用户更快地查找和访问;有些构建在Memcached的API上,缓存提供应用中使用最多的数据的内存快照。缓存的目的是减少磁盘I/O。它可以是最简单的映射表,也可以是支持缓存过期策略的健壮系统。作为一种流行策略,缓存广泛应用于计算机软件栈的所有层面以提高性能。操作系统、数据库、中间件和各种应用都使用缓存。还有一些其他实现方案,具体包括Membase、Kyoto Cabinet、Redis、Cassandra、Riak和Voldemort等。
Membase是基于Memcached的键/值存储NoSQL,它支持Memcached的文本和二进制协议,并在Memcached基础上增加了很多新特性,包括磁盘持久化、数据复制、在线集群配置和数据动态平衡。
Kyoto Cabinet的数据记录保存在简单数据文件中,每条记录是一个键/值对,每个键和值都是一组变长二进制数据。
Redis像Memcached一样,整个数据库加载到内存中进行操作,它定期通过异步操作把数据flush到硬盘上进行保存。Redis除了映射表外,还支持字符串、列表和集合等数据结构,并且提供了一套丰富的API访问不同类型数据结构的数据。从本质上讲,Redis是一个键/值类型的内存数据库。
Cassandra、Riak和Voldemort具有Apiazon Dynamo键/值特性,Cassandra和Riak的行为和属性分别显现出各自的双重性:Cassandra同时拥有Google Bigtable和Amazon Dynamo的属性,而Riak既是键/值存储数据库又是文档数据库。
Amazon Dynamo推出了大量重要的高可用性思想,其中最重要的是最终一致性(eventual consistency),最终一致性暗示出结点数据更新过程中副本可能会出现暂时性的不一致。最终一致不是不一致,只是与关系型数据库典型的ACID(原子性Atomicity、一致性Consistency、隔离性Isolation、持久性Durabilty)一致性相比更弱。
键/值存储数据库具有以下优点:
轻量级的设计,使键/值存储数据库可以很容易地实现可伸缩性以及高性能。
键/值存储数据库具有以下缺点:
(1)键/值存储数据库没有像关系型数据库从底层确保数据的完整性的措施和机制,数据的完整性必须由应用程序来完成。
(2)键/值存储数据库不如关系型数据库的模型设计良好,其数据库的逻辑结构就能完全反映出存储数据的结构,并且与应用的结构有所不同(数据是独立于应用的),因此难以取得数据是独立于应用的效果。
键/值存储数据库适用的场景:
(1)存放会话信息:通常来说,每一次网络会话都是唯一的,所以分配给它们的sessionID值各不相同。如果应用程序原来要把sessionID存在磁盘上或关系型数据库中,那么将其迁移到键/值存储数据库之后会获益良多,因为全部会话内容都可以用一条PUT请求来存放,而且只需一条GET请求就能取得。由于会话中的所有信息都放在一个对象中,所以这种“单请求操作”(single-request operation)很迅速。许多网络应用程序都使用像Memcached这样的解决方案。如果“可用性”较为重要,可使用Riak。
(2)用户配置信息:几乎每位用户都有userID、username或其他独特的属性,而且其配置信息也各自独立,例如语言、颜色、时区、访问过的产品等。这些内容可全部放在一个对象里,以便只用一次GET操作即获取某位用户的全部配置信息。同理,产品信息也可如此存放。
(3)购物车数据:电子商务网站的用户都与其购物车相绑定。由于购物车的内容需要在不同时间、不同浏览器、不同计算机、不同会话中保持一致,所以可把购物信息放在value属性中,并将其绑定到userID这个键名上。此类应用程序最宜使用Riak集群了。
3.4.3 面向文档数据库
面向文档数据库不是人们常见的文档管理信息系统,这里“文档”的意思是指松散结构的键/值对集合,通常是类似于JSON(JavaScript Object Notation,JavaScript对象表示法)格式的数据。文档数据库把文档作为基本单元,不把文档分割成多个键/值对。不同结构的文档被放在一个集合里。文档数据库支持文档索引,包括主标识符和文档属性。面向文档的NoSQL有MongoDB和CouchDB。
MongoDB是一个高性能、开源、没有模式的文档型数据库,在功能上最接近关系型数据库的NoSQL数据库,它扩展了关系型数据库的很多功能,例如辅助索引、范围查询和排序等;访问方法支持JavaScript命令行接口;支持多语言驱动,包括C、C#、C++、Erlang、Haskell、Java、JavaScript、Perl、PHP、Python、Ruby以及Scala;查询语言为类SQL查询语言。
CouchDB是一个用Erlang语言开发的面向文档的数据库,文档格式采用JSON格式;底层结构由一个存储单元(storeage)和多个视图索引(view indexs)组成;存储单元用来储存文件,视图索引用于处理查询。访问方法支持REST高于其他一切机制;也可以用标准Web工具和客户端访问数据库,和访问Web资源的方法相同;官方在线资源为“http://couchdb.apache.org”和“www.couchbase.com”;大部分作者属于Couchbase公司。
面向文档数据库具有以下优点:
(1)足够灵活的查询语言。
(2)易于水平扩展。
面向文档数据库具有以下缺点:
在很多时候原子性是得不到保障的。
文档数据库适用的场景:
(1)事件记录:应用程序对事件记录各有需求。在企业级解决方案中,许多不同的应用程序都需要记录事件。文档数据库可以把所有不同类型的事件都存起来,并作为事件存储的“中心数据库”(ccntral data sore)使用。如果事件捕获的数据类型一直在变,那么就更应该用文档数据库了。另外,可以按照触发事件的应用程序名“分片”,也可以按照order_processed或customer_logged等事件类型“分片”。
(2)内容管理系统及博客平台:由于文档数据库没有“预设模式”(predefined schema),而且通常支持JSON文档,所以它们很适合用在内容管理系统(content management system)及网站发布程序上,也可以用来管理用户评论、用户注册、用户配置和面向Web文档(web_facing document)。
(3)网站分析与实时分析:文档数据库可存储实时分析数据。由于可以只更新部分文档内容,所以用它来存储“页面浏览量”或“独立访客数”(unique visitor)非常方便,而且无须改变模式即可新增度量标准。
3.4.4 图形数据库
图形数据库指的是使用图结构的数据库,通过结点、边与属性来表示和存储数据。根据定义,图形数据库是一种提供了无须索引而彼此邻接的存储系统。这意味着每个元素都包含了直接指向邻接元素的指针,因此没必要再通过索引进行查找了。比较典型的图形数据库有Neo4j和FLockDB。
Neo4j是一个兼容ACID特性的图形数据库,便于快速遍历图形数据,支持命令行接口和REST接口,有多种语言客户端,包括Java、Python、Ruby、Clojure、Scala和PHP。支持SPARQL协议和RDF查询语言。
FlockDB由Twitter开发而成,最初是为了存储Twitter的粉丝关系表,是于2010年开源的面向文档数据库,它支持Thrift和Ruby客户端访问。
图形数据库具有以下优点:
(1)对于关联数据集的查找速度更快。
(2)可以很自然地扩展为更大的数据集,因为它们无须使用代价高昂的连接运算符。
图形数据库具有以下缺点:
图形数据库只适合类似于图的数据。
图形数据库适用的场景:
(1)互联数据:部署并使用图形数据库来处理社交网络非常高效。社交图里并不是只能有“朋友”这种关系,例如也可以用它们表示雇员、雇员的学识,以及这些雇员与其他雇员在不同项目中的工作位置。任何富含链接关系的领域都很适合用图形数据库表示。假如同一个数据库含有不同领域(像社交领域、空间领域、商务领域等)的领域实体,而这些实体之间又有关系,那么图形数据库提供的跨领域遍历功能可以让这些关系变得更有价值。
(2)安排运输路线、分派货物和基于位置的服务:投递过程中的每个地点或地址都是一个结点,可以把送货员投递货物时所经全部结点建模为一张结点图。结点间关系可带有距离属性,以便高效地投递货物。距离与位置也可用在名胜图(graph of places of interest)中,这样应用程序就可向用户推荐其附近的好餐馆及娱乐场所了,还可将书店、餐馆等销售点(point of sales)做成结点,当用户靠近时通知他们,以提供基于位置的服务。
(3)推荐引擎:在系统中创建结点与关系时可以用它们为客户推荐信息,例如“您的朋友也买了这件产品”或“给这些货品开发票时,通常也要为那些货品一并开票”,还可以用它们向旅行者提出建议,例如“来九寨沟旅游的人一般都会去看看都江堰水利工程”。
3.4.5 对象数据库
面向对象是一种认识方法学,也是一种新的程序设计方法学。把面向对象的方法和数据库技术结合起来可以使数据库系统的分析、设计最大程度地与人们对客观世界的认识相一致。数据库中的数据都建模为对象、属性、方法以及类。面向对象的数据库通常适合于需要高性能数据处理的应用,这种应用一般都有非常复杂的结构,比较典型的对象数据库有Db4o。
Db4o是一个开源的纯面向对象数据库引擎,对于Java与.NET开发者来说都是简单、易用的对象持久化工具。Db4o的一个特点就是无须DBA的管理,占用的资源很少,这很适合嵌入式应用以及Cache应用,所以自从Db4o发布以来,迅速吸引了大批用户将Db4o用于各种各样的嵌入式系统,包括流动软件、医疗设备和实时控制系统。使用db4o仅需引入400多千字节的JAR文件或是DLL文件,内存消耗极小。Db4o的目标是提供一个功能强大、适合嵌入的数据库引擎,可以工作在设备、移动产品、桌面以及服务器等各种平台。
对象数据库具有以下优点:
(1)与关系记录相比,对象模型最适合展现现实世界,对于复杂、多方位的对象来说尤其如此。
(2)使用层次特性来组织数据。
(3)访问数据时并不需要专门的查询语言,因为访问是直接面向对象的。然而,有时也是需要使用查询的。
对象数据库具有以下缺点:
(1)在关系型数据库管理系统(RDBMS)中,由于表的创建、修改或删除而导致的模式修改通常并不依赖于应用。在使用对象数据库的应用中,模式修改类通常意味着还要对与当前类关联的其他应用类进行修改,这会导致对整个系统进行修改。
(2)对象数据库通常会通过单独的API与特定的语言绑定,只有通过该API才能查询数据。在这方面,关系型数据库管理系统(RDBMS)做得很好,这要归功于它所使用的通用查询语言。