【问题标题】:Inner Join vs Subquery efficiency内连接与子查询效率
【发布时间】:2019-08-19 02:02:42
【问题描述】:

我有两个 SQL 表,Countries 和 CountryI18N:

Countries > Code
CountriesI18N > CountryCode, LanguageCode, Name

我得到一个选择以下国家的列表:

  1. 国家代码。
  2. 给定语言的国家名称I18N。

第一个 T-SQL 选项如下:

SELECT [x].[Code], (
  SELECT TOP(1) [z].[Name]
  FROM [CountriesI18N] AS [z]
  WHERE ([z].[LanguageCode] = 'en' AND ([x].[Code] = [z].[CountryCode])
) AS [Name]
FROM [Countries] AS [x]

以及使用 Inner Join 的替代方法:

SELECT [x].[Code], [x.CountriesI18N].[Name]
FROM [Countries] AS [x]
INNER JOIN [CountriesI18N] ON [x].[Code] = [x.CountriesI18N].[CountryCode]
WHERE [x.CountriesI18N].[LanguageCode] = 'en'

它们在速度和效率方面是否相当?

如果我将有许多相关表,使用许多 InnerJoins 或子查询是否等效?

【问题讨论】:

  • 打开 SSMS。按<ctrl>+N。在新的查询窗口中,粘贴两个查询。按<ctrl>+M。运行查询。检查执行计划。 Race your horses.
  • "子查询" = 子查询 :)
  • 简短回答:it depends。表大小、索引、碎片、数据类型,甚至表中的列数,它们都会产生影响。 一般如果你可以写成JOIN,你可能应该;优化器最熟悉这一点,人类更容易阅读和维护等等。但是哪个使用最多的资源,哪个更快(它们不是同一件事;单线程计划可以采取比多线程计划更长,但使用更少的资源)最好使用 SQL Server 的分析器和/或查看执行计划来衡量。
  • 另外,您的查询也不相同。第一个保证每个代码一个名称。第二个允许每个代码有多个名称的可能性。他们可以产生不同的结果可能意味着他们产生不同的执行计划。更有理由检查执行计划以了解它们有多大不同,并使用分析器准确衡量资源的使用情况。
  • @MatBailie 如何更改第二个查询以仅获取一个名称?事实上,在 CountryLocalization 中,我对 有一个独特的约束,因为那是 PK。所以我知道对于每个 LanguageCode 我只会得到一个 Name。

标签: sql sql-server tsql sql-server-2014


【解决方案1】:

首先,它们不是等效的查询。对于您的特定数据,它们可能看起来等效,但实际上并非如此。子查询最多返回一个匹配项。 inner join 过滤掉不匹配并可以返回重复项。

所以,你是在比较苹果和橙子。

在任何一种情况下,您都需要一个索引 CountriesI18N(CountryCode, LanguageCode)。这恰好是两个版本的查询的最佳索引。

【讨论】:

  • (CountryCode, LanguageCode) 已经是 CountryI18N 的 PK 作为复合键...所以涵盖了它,对吧?
  • 是的,我知道它们是不一样的......我会尝试一些类似于子查询的内部连接来在相似的条件下进行比较
猜你喜欢
  • 2013-04-26
  • 2017-03-15
  • 2020-05-21
  • 2019-05-06
  • 1970-01-01
  • 2010-09-13
  • 2015-03-29
相关资源
最近更新 更多