SQL内连接与子查询

时间:2013-05-02 14:00:07

标签: sql sql-server sql-server-2008

我正在处理以下问题:

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探查器调查这些查询并发现了一些有趣的事实。

  • 查询1需要2.312秒
  • 查询2需要0.811秒
  • 查询3需要0.944秒

TabA 48716行

TabB 62719行

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

4 个答案:

答案 0 :(得分:3)

如果我不得不猜测我会说这是因为查询1从两个表中提取数据。查询2和3(aprox同时)仅为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更多的逻辑读取。

修改

出于好奇,我做了一些测试,并在结果here上写了博客。

答案 1 :(得分:2)

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

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

答案 2 :(得分:1)

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

我必须承认,我并不认为这会有很大的不同。

答案 3 :(得分:0)

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