| 
 咨询电话:010-51727811/12/13
当前位置: 首页 > 新闻中心 > 业内新闻 >
无模式数据库NoSQL讲解
时间:2014-03-03 09:23  来源:飞客数据恢复   作者:飞客数据恢复工程师
很多NoSQL 数据库有个共同点,那就是它们都没有模式。若要在关系型数据库中存储数据,首先必须定义“模式”,也就是用一种预定义结构向数据库说明:要有哪些表格,表中有哪些列,每一列都存放何种类型的数据。必须先定义好模式,然
后才能存放数据。
 
相比之下,NoSQL 数据库的数据存储就比较随意了。“键值数据库”可以把任何数据存放在一个“键”的名下。“文档数据库”实际上也如此,因为它对所存储的文档结构没有限制。在列族数据库中,任意列里面都可以随意存放数据。你可以在图数据库中新增边,也可以随意向节点和边中添加属性。
 
无模式数据库的倡导者们很享受它所带来的自由与灵活。如果用了模式,那么就必须提前指明你要存储的数据,然而这一点却比较难办。摆脱模式的制约后,就可以轻易存储所需数据了,于是我们很容易就能根据项目的进展情况来修改原有的数据存储方式,一旦发现了新东西,只要把它们加入数据库中就好。此外,若是发现某些东西已经没用了,那么不再存储它们就行了。在使用模式的关系型数据库中,如果删除了某列,那么你恐怕得担心此操作会不会导致旧数据丢失。
 
除了更改数据方面的差别外,无模式数据库也更容易处理“格式不一致的数据”(nonuniform data),也就是那种每条记录都拥有不同字段集(set of field)的数据。“模式”会将表内每一行的数据类型强行统一,若不同行所存放的数据类型不同,那这么做就很别扭。要么得分别用很多列来存放这些数据,而且把用不到的字段值填成null (这就成了“稀疏表”,sparse table),要么就要使用类似custom column 4 这样没有意义的列类型。而无模式表则没有这么麻烦,每条记录只要包含其需要的数据即可,不用再担心上面的问题了。
无模式数据库很吸引人,而且确实能避免使用“固定模式数据库”(fixed-schemadatabase)时所面临的诸多麻烦,不过,它自身也存在一些问题。若存储数据就是为了将其显示成一列“字段名:字段值”(fieldName :value)格式的简单报表,那“模式”的确是个障碍。
 
可是,通常我们在处理数据时所要完成的任务并不止于此,而且处理数据的程序需要知道存放账单地址的字段叫做billingAddress 而非addressForBilling,quality 字段应该包含整数“5”而非单词“five”。
 
在编写数据访问程序时,必须面对一个关键问题:尽管有时不甚方便,但程序通常要依赖于某种形式的“隐含模式”(implicit schema)。除非只需要执行下面这种极为简单的逻辑。

// pseudo code
foreach (Record r in records) {
  foreach (Field f in r.fields) {
          print (f.name, f.value)
        }
}

复制代码
否则,程序必须假定表中存在某些特定的字段名,这些字段中包含带有一定意义的数据,而且还要假定该字段存有某种类型的数据。程序与人类不同,它们不能在看到“qty”后立刻推断出它与“quality”的意义一样,至少在我们没有专门为其编写特定处理代码时,它不行。所以说,不管数据库“无模式”到何种地步,总会存在“隐含模式”。它是指在编写数据操作代码时,对数据结构所做的一系列假设。
应用程序代码中的隐含模式会带来一些问题。它意味着,要想理解数据库中存放的数据,必须深入研究应用程序的代码才行。若代码结构非常好,那么你就可以根据它明确推断出数据的模式了,然而这一点却无法保证,因为它完全取决于应用程序的代码是否清晰。此外,无模式数据库感知不到模式,所以它无法用模式来提升存储与获取数据的效率,它也无法自行验证数据,以防止多个应用程序以不一致的方式操作其数据。
 
上述问题就是关系型数据库采用固定模式的原因,而且过去的数据库基本都使用固定数据模式,也正是基于此种考量。“模式”有其价值,而NoSQL 数据库弃用模式,真是个相当令人吃惊的决定。
 
从本质上说,无模式数据库是把模式交由访问其数据的应用程序代码来处理。如果由多位开发者制作的不同程序要访问相同的数据库,那就麻烦了。有几个办法能缓解此问题。一个办法就是,将所有数据库互动操作封装成独立的应用程序,并通过Web 服务将它与其他应用程序集成。当前很多开发者都通过Web 服务集成应用程序,该方法非常适合此类开发场景。还有一种办法是,在聚合中为不同应用程序明确划分出不同区域。在文档数据库中,可以把文档分成不同的区段(section);在列族数据库中,可以把不同的列族分给不同的应用程序。
 
尽管NoSQL 支持者经常批评关系型数据库,说它必须预定义模式,而且其模式也很不灵活,但事实并非如此。关系型数据库的模式随时可以通过标准SQL 命令修改。
 
在必要时,可以立即添加新列,以存储“类型不一致的数据”。我们只是很少碰到这种情况罢了,但如果真的遇上了,那此方法完全能应付。然而,在大多数情况下,如果你发现待存储的数据类型不统一,那么应该优选无模式数据库。
无模式数据库一直深远地影响着数据库的结构变更,尤其是存储格式不一致的数据时更是如此。关系型数据库的模式也可以用可控的方式改变,只是其运用范围没有理想中那么广罢了。同理,也可以控制无模式数据库存储数据的方式,让访问新、旧数据都比较容易。此外,“无模式”的灵活性仅限于聚合内部,如果改动了聚合边界,那么其数据迁移工作与关系型数据库一样,都非常复杂。