你怎么不加入?

时间:2009-01-04 20:40:41

标签: database performance optimization schema scalability

我最近一直在阅读有关数据库查询中的连接如何减慢速度的问题。显然,Google App Engine甚至不允许使用它们。

我想知道人们如何设计一个没有连接的应用程序。例如,我正在处理具有contactsorganizations的应用。联系人可以在许多组织中,组织可以有许多联系人。如果没有连接两个实体的第三个表,那怎么可能有这种关系...

contacts --< contacts_organizations >-- organizations

这是否意味着在GAE中你不能拥有多对多的关系?您只是遗漏了需要加入的功能?

我猜你可以在organizations表中有一个TEXT contacts列,其中包含每个联系人的组织ID的空格分隔列表。这看起来有点奇怪。

7 个答案:

答案 0 :(得分:13)

这是一个加速减速软件的神话,就像在应用程序代码中断言写入循环减慢软件一样神话般的神话。

我的意思是,为什么要写一个循环?这只是一次又一次地运行相同的代码行!还不够吗?这是一个巨大的浪费!

以上陈述具有讽刺意味。

我的观点是,查询包含用于目的的连接:获得正确的答案。低效或不必要地使用连接当然是糟糕的设计,比如将循环不变代码放在循环中。

作为一般政策避免加入是过早优化的一个示例。如果您编写高效代码的方法是提出类似的一揽子规则,那么避免连接对您没有帮助。


对于Google App Engine,它确实支持实体之间的关系,但由于它不是严格意义上的关系数据库模型,因此连接的概念并未真正出现。相反,您可以从给定引用中获取相关实体,这更像是模型的ORM接口,它与SQL中的连接不同。

您可以在这里阅读更多内容: http://code.google.com/appengine/articles/modeling.html

(该链接在此主题的另一个答案中,但已被删除)

答案 1 :(得分:7)

Nit-picking point:Google不会在其数据库中禁止使用JOIN来阻止用户运行“昂贵”的查询;数据库不是关系型的,因此“JOIN”SQL动词首先并不适用。

通过这种方式,BigTable与Amazon's SimpleDB相同 - 数据被非规范化并剥离了模式,因此您可以有效地使用存储桶中允许的任意数据的大型高效哈希表。

这些哈希表非常容易扩展,特别是与关系数据库相比。对于像GAE这样的应用程序,极端可伸缩性比完整功能集具有更高的优先级。

答案 2 :(得分:3)

您使用db.ReferenceProperty链接对象,有关详细信息和示例,请参阅Google App Engine: One-to-many JOIN

答案 3 :(得分:3)

通常,当您谈论不允许连接的数据库时,您谈论的是非常大的数据库,它们不一定适合一台服务器。最近的示例是像Amazon's SimpleDBMicrosoft's SQL Data ServicesGoogle's App Engine Datastore这样的云数据库。有些提供有限的连接功能,但最大的困难是在“partitions”之间进行连接。在像这样的大型数据库中,您对数据进行分区,使其不必驻留在同一服务器上。你必须决定分区的正确方法。

在您的示例中,我将在联系人表中的字段中存储组织键列表,反之亦然。这些数据库的设计与典型的规范化数据库不同。这些表通常是“稀疏表”,这基本上意味着每个记录可以具有任意数量的字段,这些字段基本上是名称/值对。想想亚马逊上的产品表,以及不同类型产品可能有多少个不同的字段。书籍有多少页面,但MP3有持续时间。在稀疏表中,这些记录将存储在同一个表中。

答案 4 :(得分:1)

我认为谷歌正在试图利用一些计算量很大的机制,因此您将寻找可以利用更多其他资源的方法,例如维护参考表和/或计数表的硬盘而不是CPU周期浪费加入和汇总计算。

这并非不可能,您只需使用其他种资源来帮助您解决问题。

答案 5 :(得分:1)

您可以在应用程序而不是数据库服务器中执行连接,方法是分别从每个表中获取结果然后将它们组合在一起,但对于大多数连接而言,这样做只会因为进行多次数据库往返的延迟而减慢速度而不只是一个。

但是:诚实的事实是连接不是你的问题。到他们的时候,如果有的话,你甚至不需要问这个问题。你可以计算出你手指上的现实生活项目的数量(主要是Ebay),并且没有证据表明完全消除连接是这些项目可以扩展的唯一方式。

答案 6 :(得分:0)

您提到的数据库充其量只是版本化的记录存储,旨在跨多个服务器存储大量数据。称他们为“数据库”将是一个延伸。不支持连接,也不支持ACID事务,回滚等。您可以在没有它们的情况下编写应用程序,但通常需要做更多工作来提供功能。

有关:

contacts --< contacts_organizations >-- organizations

您可以在组织中的联系人和联系人中存档和存储组织。但是,您必须在应用程序处理中强制执行引用完整性,同时更新到两个表。

更好的解决方案是将数据存储在三个表中并自己进行“连接”。