20

我是数据库新手,从未使用过任何 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 和 city 的值,我必须运行第二个查询。但在另一种情况下,要更改邮政编码,我必须遍历所有现有用户。

那么这两种建模可能性在像谷歌数据存储这样的非关系数据库中的含义是什么。以及它们的典型用例是什么,这意味着我什么时候应该使用一个,什么时候使用另一个。

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

抱歉,如果其中一些问题听起来很幼稚,但我相信它们会帮助一些刚接触数据库系统的人更好地理解。

4

3 回答 3

17

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

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

于 2011-05-13T17:33:34.340 回答
11

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

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

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

我们的 RDMS 系统已经处理了语义背后数据的反规范化,并且在一次查询中返回了我们需要的所有数据方面做得很好。这个查询确实有一点开销,因为它必须将我们的两个表拼接在一起。

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

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

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

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

现在,无论他们是否使用 RDMS,每个人都会在某种程度上对他们的数据进行逻辑规范化,诀窍是为您的用例找到便利性和性能之间的权衡。

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

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

关系型数据库擅长存储成千上万行复杂的相互关联的数据模型,并允许您执行极其复杂的查询来重构和访问该数据。

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

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

于 2011-05-13T19:13:54.020 回答
4

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

您提供的使用外键的示例演示了数据库规范化。这是一个可以应用于关系数据库以及其他类型的数据库的概念。

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

于 2011-05-13T17:03:40.437 回答