【问题标题】:SQL: Performance comparison for exclusion (Join vs Not in)SQL:排除的性能比较(加入与不加入)
【发布时间】:2011-03-06 05:56:12
【问题描述】:

我很好奇在 sql 上查询排除的最有效方法。例如。有 2 个表(tableA 和 tableB)可以连接到 1 列(col1)。我想为tableB中不存在col1的所有行显示tableA的数据。

(也就是说,tableB 包含 tableA 的 col1 的一个子集。我想显示 tableA 而没有 tableB 中存在的数据)

假设 tableB 有 100 行,而 tableA 是巨大的(超过 1M 行)。我知道可以使用“不在(不存在)”,但也许有更有效的方法(更少的补偿时间)来做到这一点。?我可能没有外部连接?

非常感谢代码 sn-ps 和 cmets。

【问题讨论】:

  • 什么 DBMS? SQL Server、MySQL、甲骨文?这些查询优化器的功能不同。
  • 甲骨文。如果各种 DBMS 之间存在显着的性能差异,我会感到惊讶。
  • 是的,你会感到惊讶。 :)

标签: sql performance join


【解决方案1】:

这些问题已经被问过好几次了。通常最快的方法是这样做:

SELECT * FROM table1 
WHERE id in (SELECT id FROM table1 EXCEPT SELECT id FROM table2)

因为整个连接可以在索引上完成,而使用 NOT IN 通常不能。

【讨论】:

  • 感谢您的回答。我找不到以前提出的问题。
  • 例如我认为类似:stackoverflow.com/questions/3074862/…
  • 是的,类似。但是很难找到这个问题,因为它缺乏详细的描述和标签。你知道它是因为你在 2 天前回答了这个问题:)
  • 呵呵。是的,我也尝试过自己先手动搜索找到它,但我做不到。所以我可能在那里有优势;)
  • 您有任何引用来支持您的声明吗?我有兴趣查看一些统计数据。
【解决方案2】:

我更喜欢使用

Select a.Col1
From TableA a
Left Join TableB b on a.Col1 = b.Col1
Where b.Col1 Is Null

我相信这会更快,因为您正在使用 FK 约束(假设您有 他们当然)

样本数据:

create table #a
(
Col1 int
)
Create table #b
(
col1 int
)

insert into #a
Values (1)
insert into #a
Values (2)
insert into #a
Values (3)
insert into #a
Values (4)

insert into #b
Values (1)
insert into #b
Values (2)


Select a.Col1
From #a a 
Left Join #b b on a.col1 = b.Col1
Where b.Col1 is null

【讨论】:

  • 感谢您的回答,但此解决方案对我不起作用。一个原因是 Col1 不能为空(tableB 只有 Col1)。所以你的解决方案没有给我任何结果。
  • @Masa44 - 你确定吗?它对我有用。我添加了一些测试数据作为示例。
  • 巴里,谢谢你的例子。你的例子工作得很好,但我没有这样做,我想我犯了一个小错误。
【解决方案3】:

取决于 RDBMS。对于 Microsoft SQL Server NOT EXISTS is preferred 到 OUTER JOIN,因为它可以使用更高效的反半连接。

对于 Oracle Minus is apparently preferred 不存在(在合适的情况下)

您需要查看执行计划并做出决定。

【讨论】:

  • 感谢您的回答。我感兴趣的 DBMS 是 Oracle。您确定 Minus 比使用 join 或 inflagranti 的答案的查询更有效吗?
  • @masa44 一点也不。虽然 inflagranti 的答案使用了 EXCEPT,它在 Oracle 中是 is 减号。建议是查看执行计划。
  • +1 用于建议调查执行计划(在具有更新统计信息的真实数据上)。还有一个问题是存在哪些索引。
  • 感谢 Martin Smith,很好的推荐。如果可以的话,我也会投票赞成 :)
【解决方案4】:

这个问题没有正确答案。每个 RDBMS 都有查询优化器,它将根据可用索引、表统计信息(行数、索引选择性)、连接条件、查询条件……确定最佳执行计划。

当您在问题中遇到相对简单的查询时,通常可以通过多种方式在 SQL 中获取结果。无论您使用哪种语法(使用 IN 或 EXISTS 运算符的子查询、使用 JOIN 的查询……),每个自尊的 RDBMS 都会识别您的意图并创建相同的执行计划。

因此,最好的解决方案是编写最简单的有效查询,然后检查执行计划。
如果该解决方案不可接受,那么您应该尝试找到更好的查询。

【讨论】:

  • 不,数据库不会为具有相同结果集的不同类型的查询生成相同的计划。如果您逐个查看供应商,您会发现哪些是执行特定类型查询的最有效方法。
  • @HLGEM 您显然从未在上述情况下查看过 Oracle 中的执行计划。
  • 不,我看一下 SQL Server 中的执行计划,其中对于同一查询的不同方法之间存在巨大差异。并且知道我知道先尝试哪种类型。编写最简单的查询只是不好的建议。并且“每个自尊的 RDBMS 都会识别您的意图并创建相同的执行计划,无论您使用哪种语法”都是错误的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-28
  • 1970-01-01
  • 2013-01-13
  • 2011-03-18
  • 1970-01-01
相关资源
最近更新 更多