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

znq*_*znq 20 google-app-engine data-modeling non-relational-database 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()
Run Code Online (Sandbox Code Playgroud)

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

因此,现在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)
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

mor*_*aes 17

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

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

  • +1很棒的答案.现在我想起来了,我没有意识到这一点. (3认同)
  • 这正是我要写的内容.:) (3认同)

Chr*_*loe 11

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

对于[虚构] RDMS模式数据存储区,它可能看起来像:

for user in User.all().join("location"):
    print("name: %s zip: %s" % (user.name, user.location.zip))
Run Code Online (Sandbox Code Playgroud)

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

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

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

在这里,数据存储无法帮助我们加入我们的数据,我们必须为每个user实体做一个额外的查询,以便location在我们打印它之前获取它.

这实际上是为什么要避免非RDMS系统上过度标准化的数据.

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

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

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

relational-DB擅长存储数千万行复杂的相互关联的数据模型,并允许您执行难以置信的错综复杂的查询来改革和访问该数据.

非RDB擅长存储数十亿行简单数据,并允许您使用更简单的查询获取该数据.

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


Jak*_* T. 4

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

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

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