关系与非关系数据建模 - 有什么区别

时间:2011-05-13 16:42:03

标签: google-app-engine data-modeling relational-database non-relational-database

我是数据库的新手,我从未使用过任何RDBMS。但是我得到了关系数据库的基本概念。至少我认为我做了; - )

假设我有一个用户数据库,每个用户都有以下属性:

  
      
  • 用户   
        
    • ID
    •   
    • 名称
    •   
    • 拉链
    •   
    • 城市
    •   
  •   

关系数据库中,我会在名为user

的表格中对其进行建模
  
      
  • 用户   
        
    • ID
    •   
    • 名称
    •   
    • LOCATION_ID
    •   
  •   

并有一个名为location

的第二个表
  
      
  • 位置   
        
    • ID
    •   
    • 拉链
    •   
    • 城市
    •   
  •   

location_idlocation表中条目的外键(引用)。如果我理解正确的优势就在这里,如果某个城市的邮政编码发生变化,我只需更改一个条目。

所以,让我们转到非关系数据库,在那里我开始使用Google App Engine。在这里,我真的会对它进行建模,就像它在规范中首先写下来一样。我有一种user

class User(db.Model):
    name = db.StringProperty()
    zip = db.StringProperty()
    city = db.StringProperty()

优点是我不需要加入两个“表”,但缺点是,如果邮政编码改变,我必须运行一个遍历所有用户条目并更新邮政编码的脚本,对吗?

因此,现在Google App Engine中还有另一个选项,即使用ReferenceProperties。我可以有两种:userlocation

class Location(db.Model):
    zip = db.StringProperty()
    city = db.StringProperty()

class User(db.Model):
    name = db.StringProperty()
    location = db.ReferenceProperty(Location)

如果我没错,我现在拥有与上述关系数据库完全相同的模型。我现在想知道的是,首先,我所做的是错误的,这会破坏非关系型数据库的所有优点。我明白,为了获得zip和城市的价值,我必须运行第二个查询。但在另一种情况下,要对邮政编码进行更改,我必须在所有现有用户中运行。

那么在Google的数据存储区等非关系型数据库中,这两种建模可能性的含义是什么?它们的典型用例是什么,这意味着何时我应该使用一个用户,何时用另一个用途。

另外作为一个额外的问题,如果在非关系型数据库中我可以建模与关系数据库中的模型完全相同的模型,为什么我应该使用关系数据库呢?

很抱歉,如果其中一些问题听起来很幼稚,但我相信他们会帮助一些不熟悉数据库系统的人,以便更好地理解。

3 个答案:

答案 0 :(得分:17)

根据我的经验,最大的区别在于非关系数据存储会因为交易限制而迫使您根据查询方式进行建模,因为缺少连接以及您将如何编写。这当然导致非常规范化的模型。过了一会儿,我开始定义所有查询第一次,以避免以后重新考虑模型。

由于关系数据库的灵活性,您可以单独考虑每个数据系列,在它们之间创建关系,最后查询您的意愿(在很多情况下滥用连接)。

答案 1 :(得分:11)

想象一下,GAE有两种数据存储模式:RDMS模式和非RDMS模式。 如果我采用您的ReferenceProperty示例,目的是“列出所有用户及其所有邮政编码”,并编写一些代码来打印所有这些。

对于[虚构的] RDMS模式数据存储区,它可能如下所示:

for user in User.all().join("location"):
    print("name: %s zip: %s" % (user.name, user.location.zip))

我们的RDMS系统处理了senes背后数据的非规范化,并且很好地返回了一个查询中所需的所有数据。这个查询确实有一些开销,因为它必须将我们的两个表拼接在一起。

对于非R​​DMS数据存储区,我们的代码可能如下所示:

for user in User.all():
    location = Location.get( user.location )†
    print("name: %s zip: %s" % (user.name, location.zip))

下面的数据存储不能帮助我们加入我们的数据,我们必须为每一个user实体,以获取location之前,我们可以打印一个额外的查询。

这实质上就是为什么你要避免在非RDMS系统上过度规范化的数据。

现在,每个人在逻辑上将他们的数据标准化到某种程度,无论他们是否正在使用RDMS,诀窍是找到便利性和性能之间的权衡。

†这不是有效的appengine代码,我只是说明user.location会触发数据库查询。也没有人应该像上面我的极端例子那样编写代码,你可以通过预先批量获取位置来解决相关实体的持续提取问题。

  

如果在非关系型数据库中我的模型与我在关系数据库中建模的模型完全相同,为什么我应该使用关系数据库呢?

在存储成千上万和数百万的数据的复杂的相互关联的模型行,并允许你进行难以置信的复杂的查询,以改革和访问关系-DB的Excel中的数据。

非RDB擅长存储数十亿行简单数据,并允许您通过更简单的查询获取数据。

选择应该在于您的用例。随之而来的非关系模型的简单结构和设计限制是AppEngine能够承诺按需扩展应用程序的主要方式之一。

答案 2 :(得分:4)

您对关系数据库概念的理解存在缺陷。关系数据库在关系中组织它们的数据,这些关系包含一组相同类型的元组。换句话说,数据存储在表中,每行包含相同数量的字段,具有相同类型的相同顺序。

您提供的使用外键的示例演示database normalization。这个概念可以应用于关系数据库以及其他类型的数据库。

很抱歉,我无法解答有关Google存储系统的问题,但希望这会澄清您的理解,以便找到答案。