太多的左连接是代码味道吗?

Posted

技术标签:

【中文标题】太多的左连接是代码味道吗?【英文标题】:Is too many Left Joins a code smell? 【发布时间】:2010-10-22 01:46:48 【问题描述】:

例如,如果您在查询中有 > 5 个左连接,那么代码有味道......

您的设计有问题? 您在一个查询中做的太多了吗? 你的数据库太规范了?

【问题讨论】:

应该是社区维基 @ck - 不应该;这个问题是一个非主观的可回答问题。 我的 0.02 美元:在您遇到已知的性能问题并且已经用尽简单的优化之前,没有所谓的“过于规范化”。到那时,进行一些非常受控小心的非规范化可能是合理的。 在具有自定义字段表的超规范化数据库中工作,我们做了很多连接,达到了 mysql 61 的限制,但我们遇到的性能问题仅与排序/组和 wheres 相关,而不是加入。 不,这不是气味。然而,随着混淆可能性的增加,选择好的表别名变得更加重要。您永远不应该使用代理别名,例如 a,b,c... 【参考方案1】:

对于某些设计来说,这是一个完全合法的解决方案。

假设您有一个一对多关系的层次结构,例如 Customer - Order - Basket - Item - Price 等,可以在任何级别上未填充:@987654327 @ 可能没有OrdersOrder 可能没有Baskets,等等。

在这种情况下,您会发出类似的问题:

SELECT  *
FROM    Customer c
LEFT OUTER JOIN
        Order o
ON      o.CustomerID = c.ID
LEFT OUTER JOIN
        Basket b
ON      b.OrderID = c.ID
…

注意,在某些情况下可能效率低下,可以用EXISTSNOT EXISTS代替(如果你只想弄清楚对应的记录在其他表中是否存在)。

有关性能详情,请参阅我的博客中的这篇文章:

Finding incomplete orders - 如何从 LEFT JOIN 替换为 NOT EXISTS 中受益

【讨论】:

不存在 vs 连接技术(我非常喜欢)是一个很好的观点,但连接可能是正确的。 当然。这就是为什么我写了“可能被替换”而不是“应该不惜一切代价被替换并且永远不会再次使用”:)【参考方案2】:

从某种意义上说,这是您可以/应该调查的事情,我会说是的。通过考虑其中的一些观点,您可能可以获得更好的实用性和维护性。

从某种意义上说,它是“糟糕的代码”,不,这很容易合理,尤其是对于较大的数据库,现代数据库可能会优化任何低效率。

【讨论】:

【参考方案3】:

不,这样做很好,但如果您发现自己一遍又一遍地使用相同的连接到相同的表编写相同的查询/过程, 它可能是创建视图的候选者,只是为了简化您将来的查询,并减少在架构更改时需要更改的接触点数量

【讨论】:

【参考方案4】:

很多时候你可以通过创建辅助视图来减轻视觉上的异味,我不认为有多少左连接被认为是坏的硬性规定。

与过程编码不同,将 SQL 分解成小块可能会导致查询效率低下。

【讨论】:

【参考方案5】:

你的结果我的变化

任何不寻常的东西都可能是任何东西的代码气味。就像 Quassnoi 所说的那样,它可能是完全合法的。真正深入的报告需要大量的连接来正确拼凑信息的情况并不少见。这并不意味着开发人员应该考虑对他们的数据库进行非规范化。

【讨论】:

【参考方案6】:

几乎不可能有人回答如此笼统的问题,而试图创建这样一个武断的规则毫无意义。

左连接是一种完全可以接受的连接类型,它映射到一个非常常见的需求:给我所有的 x,如果它们有关联的 y,那么也得到那些。

【讨论】:

【参考方案7】:

不,一点也不。构建在某些查询上使用大量左连接的数据库设计是完全合法的。

话虽如此,我通常更喜欢构建数据库,以便限制需要外部联接的情况数量,因为经验倾向于表明使用它们的(复杂)查询更容易出错并且可能导致维护问题。

作为一个有趣的历史,IBM 的 DB2 的早期版本仅在大型机上运行时不支持外部连接(Oracle 和 Ingress 在当时都支持,这是一个主要卖点)。这导致了数据库设计中的一些有趣问题,因为有必要确保仅使用内部连接就可以解决数据库的所有预期数据访问要求。

【讨论】:

【参考方案8】:

我认为必须使用许多连接(例如处理规范化数据)不是代码异味,而是表明您可能没有在正确的位置工作。根据我的经验,那些担心查询中的连接数量的人在数据库中开发得太多,而在公开数据的应用程序和报告中开发得不够多。数据结构必须足够灵活以支持多种用途,这就是为什么规范化在某种程度上很重要。

在构建当今的企业应用程序时,开发人员可以利用昨天的成就在 SQL 甚至 XML 等技术之上的抽象级别上工作,以便以更少的工作交付更多的价值。有一些工具,即报告编写器、代码生成器、ORM、实体框架等,可以抽象出手动构建 SQL 的低级工作,并为您执行连接。大多数人都知道正在使用的 SQL 方言(例如,Oracle 9 与 MySQL 3),并且可以生成对该方言最有效的 SQL 语法;这意味着他们可能比您更好地创建连接。

但是,在没有充分规范化的关系环境中,这些工具的工作效果很差,或者根本不工作。对我来说,这就是“发展”气味表现出来的地方。如果已建立的数据访问工具无法理解我构建数据时所依据的关系,我可能需要寻找一种更规范的方式来创建这些关系,并从中获得远远超过仅使用该工具的好处。通常,介于第 2 和第 3 normal form 之间的某个位置是最佳位置;尽管总是存在一些小的关系数据区域,在这些区域中,更高程度的规范化是有意义的并增加了价值。

干杯, 特拉维斯

【讨论】:

该死的好答案先生。

以上是关于太多的左连接是代码味道吗?的主要内容,如果未能解决你的问题,请参考以下文章

带有附加左表过滤器的左连接性能

数据库的左连接,右连接,内链接:

mysql数据库的左连接,右连接,内链接。有何区别

删除...在sqlite中的左连接查询[重复]

Linq 和 SQL的左连接右连接内链接

深入浅出:MySQL的左连接右连接等值连接