8

我正在处理以下查询:

Query 1: SELECT * From TabA INNER JOIN TabB on TabA.Id=TabB.Id
Query 2: SELECT * From TabA WHERE Id in (SELECT Id FROM TabB)
Query 3: SELECT TabA.* From TabA INNER JOIN TabB on TabA.Id=TabB.Id

我使用 SQL Server Profiler 调查了这些查询,并发现了一些有趣的事实。

  • 查询 1 耗时 2.312 秒
  • 查询 2 耗时 0.811 秒
  • 查询 3 耗时 0.944 秒

TabA 48716 行

TabB 62719 行

基本上我要问的是为什么查询 1 需要很长时间,而不是查询 3。我已经知道“子查询”比内部连接慢,但这里查询 2 最快;为什么?

4

4 回答 4

4

如果我不得不猜测,我会说这是因为查询 1 正在从两个表中提取数据。查询 2 和 3(大约同时)仅提取 TabA 的数据。

您可以检查这一点的一种方法是运行以下命令:

SET STATISTICS TIME ON
SET STATISTICS IO ON

当我跑

SELECT * FROM sys.objects

我看到了以下结果。

SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 104 ms.

(242 row(s) affected)
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'sysschobjs'. Scan count 1, logical reads 10, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'syssingleobjrefs'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'syspalnames'. Scan count 1, logical reads 2, physical reads 1, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 866 ms.

您可以查看每个查询的扫描次数、逻辑读取次数和物理读取次数。物理读取当然需要更长的时间,并且代表从磁盘读取到缓存中。如果您的所有读取都是逻辑读取,那么您的表完全在缓存中。

我敢打赌,如果你看一下,在查询 1 上的 TabB 上会比在 2 和 3 上看到更多的逻辑读取。

编辑:

只是出于好奇,我做了一些测试并将结果记录在这里

于 2013-05-02T14:44:47.310 回答
2

查询 1:
此查询返回 TabA 和 TabB 中所有行的行,因此两个表的覆盖索引需要包含每个表中的所有行。要确切了解发生了什么,您需要查看查询计划。

查询 2 和查询 3:
您从 TabA 返回所有行,并且您只需要 TabB 的 Id 列的索引。我猜这里的差异与表统计信息有关,但是(再一次)我们必须查看查询计划才能确切知道发生了什么。

于 2013-05-02T14:43:21.390 回答
1

这仅仅是因为 SQL 不必执行 JOIN。您只是在执行两个查询,其中只有一个具有 WHERE 子句。

我必须承认我没想到会有这么大的不同。

于 2013-05-02T14:04:44.857 回答
0

如果连接是一对多的,则可能需要时间的是重复数据。相反,您可以将一组相关行格式化为 JSON 数组。检查https://blogs.msdn.microsoft.com/sqlserverstorageengine/2015/10/09/returning-child-rows-formatted-as-json-in-sql-server-queries/上的“用例 1”

于 2017-12-27T15:14:22.253 回答