【问题标题】:Joins vs Join like queries - Are they equivalent?Joins vs Join like 查询 - 它们是否等效?
【发布时间】:2014-06-28 05:15:03
【问题描述】:

我希望这个问题已经被多次问过,并且有不同的曲折。不过,我想尝试对这个主题有一个通用而全面的理解。 (它是否属于编程 SO?..)

假设我有一张sports 的桌子和一张matches 的桌子。 matches 等字段中有一个 sport_id 列,这是一个 1:many 关系。

假设我想列出第 X 天有比赛的运动。我可以通过 3 种我能想到的方式来做到这一点..

嵌套查询 - 易于推理?

SELECT * 
FROM sports 
WHERE id IN (SELECT sport_id FROM matches WHERE <DATE CHECK>)

来自/哪里 - 容易写吗?

SELECT sports.* 
FROM sports, matches 
WHERE sports.id = matches.sport_id 
  AND <DATE CHECK>

加入 - 我不是太熟悉,所以请原谅任何错误

SELECT * 
FROM sports 
JOIN matches ON sports.id = matches.sport_id 
WHERE <DATE CHECK>

可能还有其他基于 Join 变体的方法可能更适合这里,可能是内部连接..

我想知道的是如何在

的基础上比较这 3 个
  1. 等效响应(返回相同的行?)
  2. DB 上的性能
  3. 它们都是 1 个查询/网络调用还是?
  4. 这些答案是否依赖于数据库引擎?
  5. 我该如何选择?
  6. #2 是#3 的语法糖吗?是#1?或者它们是否在某些/所有情况下优化为 #3?

【问题讨论】:

  • 第二个和第三个都是连接——第二个是隐式连接,第三个是显式连接。它们是完全等价的。
  • Bad habits to kick : using old-style JOINs - 旧式 逗号分隔的表格列表 样式已随 ANSI-92 SQL 标准(超过 20 年前)

标签: sql performance join


【解决方案1】:

第二种和第三种形式是完全等价的(除了在第三种版本中多了一个逗号)。 FROM sports, matches 是一个隐式 连接,FROM sports JOIN matches 是一个显式 连接。隐式连接是较早的形式,显式连接更现代,通常受到数据库专家的青睐。

WHERE IN的版本几乎相同,但有一些不同。首先,SELECT * 将返回连接中两个表的列,但在 WHERE IN 查询中只返回来自 sports 的列。其次,如果sports 中的一行匹配matches 中的多行,则连接将为每对匹配返回一行(它执行叉积),而WHERE IN 将只返回来自sports 的行一次不管有多少匹配。

性能差异取决于实现。显式连接和隐式连接之间不应该有任何区别,它们只是语法糖。但是,数据库并不总是以相同的方式优化 WHERE IN 查询。例如,当我将EXPLAIN 与 MySQL 一起使用时,WHERE IN 查询经常对外部表执行完整扫描,将列与子查询中表的索引进行匹配,即使子查询可能只返回一个小的行数。我想有些人告诉我最近的 MySQL 版本在这方面做得更好。

它们都只是 1 个网络调用。所有查询都只是对数据库服务器的一次调用。

顺便说一句,您没有列出另一种形式,使用带有相关子查询的 WHERE EXISTS

SELECT *
FROM sports s
WHERE EXISTS (SELECT 1 
              FROM matches m 
              WHERE s.id = m.sport_id AND <DATE CHECK>)

这个和JOIN 之间的性能差异将再次取决于实现。

【讨论】:

  • 嘿,谢谢,还在消化.. , 是无意的,已删除
【解决方案2】:

这是我对你的问题的看法

1.等效响应(返回相同的行?)

  • 对于您使用IN Oprator 的第一个QUERY,我的答案是否定的(您得到相同的行数,但只有来自表sports 的列) 第二个和第三个几乎一样

2.DB 上的性能

First In oprator 较慢,然后加入,因为 对 a 中的每一行评估 IN(并重新运行从 b 中选择),而优化 JOIN 以使用索引和其他巧妙的分页技巧...

ANSI JOIN 语法

SELECT fname, lname, department 
FROM names INNER JOIN departments ON names.employeeid = departments.employeeid

以前的 Microsoft JOIN 语法

SELECT fname, lname, department 
FROM names, departments 
WHERE names.employeeid = departments.employeeid

如果编写正确,任何一种格式都会产生相同的结果。但这是一个很大的假设。较旧的 Microsoft join 语法容易出错,因为语法不太明显。另一方面,ANSI 语法非常明确,几乎不会出错。

3.都是1个查询/网络调用还是?

-IN 的试用 1 结果

-Microsoft JOIN 的试验 2 结果,

-ANSI JOIN 的试验 3 结果 4.这些答案是否依赖于数据库引擎?

(对不起,我没有得到这个问题的答案)

5.我该如何选择?

我建议你使用ANSI JOIN

6.#2 是#3 的语法糖吗?是#1?或者它们是否在某些/所有情况下优化到 #3?

-我认为不,正如我上面提到的 #3 syntex 更击球手 根据我过去的经验 我从 ERP 程序中遇到了一个执行缓慢的查询。在查看了使用 Microsoft JOIN 语法的代码后,我注意到开发人员没有创建 LEFT JOIN,而是意外地创建了 CROSS JOIN。在这个特定示例中,LEFT JOIN 应该产生少于 10,000 行,但由于使用了 CROSS JOIN,因此返回了超过 1100 万行。然后,开发人员使用 SELECT DISTINCT 删除了由 CROSS JOIN 创建的所有不必要的行。您可以猜到,这是一个非常冗长的查询。我通知了供应商的支持部门,他们修复了他们的代码。

这个故事的寓意是您可能应该使用 ANSI 语法,而不是旧的 Microsoft 语法。除了减少犯傻错误的几率之外,这段代码在数据库之间更具可移植性,最终,我想微软最终会停止支持旧格式,让 ANSI 语法成为唯一的选择

【讨论】:

  • 嗨,谢谢,还在消化,但是您的“列”问题是我特别将sports.* 放在第二个的原因。我假设加入只会从FROM 表中选择* ..不是这样吗?
  • 第三个(join)查询也只返回来自sports的列。你能解释一下为什么在你的图片中微软语法说 70 返回但 join 只返回 42?
猜你喜欢
  • 2012-05-28
  • 2015-05-28
  • 2019-07-16
  • 1970-01-01
  • 2015-05-26
  • 2015-02-17
  • 1970-01-01
  • 2011-01-26
  • 2015-06-18
相关资源
最近更新 更多