关系型与非关系型数据建模

19

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

  • 用户
  • id
  • 姓名
  • 邮编
  • 城市

在关系型数据库中,我会在表user中建模:

  • 用户
  • id
  • 姓名
  • 位置_id

并且有第二个名为location的表:

  • 位置
  • id
  • 邮编
  • 城市

location_id是对location表中条目的外键(引用)。

优点是,如果某个城市的邮政编码发生变化,我只需要更改一个条目。

现在我们来看看非关系型数据库,比如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)

我拥有与关系数据库中完全相同的模型。

我刚才做的是错误的吗?

这是否破坏了非关系型数据库的所有优势?

为了获取邮政编码和城市的值,我必须运行第二个查询。但在另一种情况下,要更改邮政编码,我必须遍历所有现有用户。

这两种建模可能性在像Google数据存储这样的非关系型数据库中有什么影响?

它们的典型用例是什么--何时应该使用其中之一?

3个回答

17

根据我的经验,非关系型数据存储强制你按照查询方式进行建模,因为缺少联接和事务限制会影响编写方式。这当然会导致非常非规范化的模型。不久之后,我开始首先定义所有的查询,以避免后来需要重新思考模型。

由于关系型数据库的灵活性,你可以将每个数据家族分开考虑,在它们之间创建关系,并在最后按照自己的意愿进行查询(在许多情况下滥用联接)。


11

假设GAE有两种Datastore模式:RDMS(关系型数据库)模式和非RDMS模式。 如果我以您的ReferenceProperty示例为目标,想要“列出所有用户及其邮政编码”,并编写一些代码来打印所有这些内容。

对于[虚构的]RDMS-mode Datastore,代码可能如下:

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

我们的关系数据库管理系统已经处理了数据的反规范化,并很好地通过一次查询返回了我们需要的所有数据。这个查询确实有些开销,因为它必须将我们的两个表拼接在一起。

对于非关系数据库管理系统,我们的代码可能如下所示:

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

在这里,Datastore无法帮助我们连接数据,我们必须为每个user实体进行额外的查询以获取location,然后才能打印它。

本质上,这就是为什么你要避免在非关系型数据库系统上过度规范化数据。

现在,每个人都会根据逻辑将其数据规范化到一定程度,无论他们是否使用关系型数据库系统,诀窍在于找到您的用例的方便性和性能之间的权衡。

†这不是有效的appengine代码,我只是说明user.location会触发一个db查询。而且没有人应该编写像上面那个极端示例中的代码,您可以通过预先批量获取位置等方法来解决持续获取相关实体的问题。

如果在非关系型数据库中,我可以模拟与关系型数据库完全相同的模型,那我为什么还要使用关系型数据库呢?

关系型数据库在存储成千上万行复杂互相关联的数据模型方面表现出色,并允许您执行非常复杂的查询以重新组织和访问该数据。

非关系型数据库在存储数十亿行简单数据方面表现出色,并允许您使用更简单的查询获取该数据。

选择应该真正取决于您的用例。非关系型模型的更简单结构和与之相关的设计限制是AppEngine能够承诺根据需求扩展您的应用程序的主要方式之一。


4
你对关系型数据库的概念理解有误。关系型数据库将数据组织成包含同一类型元组集合的关系。换句话说,数据存储在表格中,每行包含相同数量、相同类型、相同顺序的字段。
你提供的使用外键的示例演示了数据库规范化的概念。这是一个适用于关系型和其他类型数据库的概念。
抱歉,我无法回答有关Google存储系统的问题,但希望这能够澄清你的理解,以便找到答案。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接