Sql server 当我的查询有Where时,为什么SQL Server有更多的I/O?

Sql server 当我的查询有Where时,为什么SQL Server有更多的I/O?,sql-server,sql-server-2012,query-optimization,Sql Server,Sql Server 2012,Query Optimization,我使用SQL Server 2012,并编写以下查询: DBCC DROPCLEANBUFFERS; SET STATISTICS IO ON; 我在上面写了两行关于清洁现金的信息,并设置了统计数据 我的问题是: SELECT C.custid, C.companyname, O.orderid, O.orderdate FROM Sales.Customers AS C INNER JOIN Sales.Orders AS O ON C.custid = O

我使用SQL Server 2012,并编写以下查询:

DBCC DROPCLEANBUFFERS;
SET STATISTICS IO ON; 
我在上面写了两行关于清洁现金的信息,并设置了统计数据

我的问题是:

SELECT C.custid, C.companyname, O.orderid, O.orderdate 
FROM Sales.Customers AS C 
     INNER JOIN Sales.Orders AS O 
        ON C.custid = O.custid 

SELECT C.custid, C.companyname, O.orderid, O.orderdate 
FROM Sales.Customers AS C 
    INNER JOIN Sales.Orders AS O 
        ON C.custid = O.custid 
WHERE O.custid < 5
选择C.custid、C.companyname、O.orderid、O.orderdate
来自销售。客户为C
内部连接销售。订单为O
在C.custid=O.custid上
选择C.custid、C.companyname、O.orderid、O.orderdate
来自销售。客户为C
内部连接销售。订单为O
在C.custid=O.custid上
其中O.custid<5
但我得到了这个统计数据:

对于第一个查询: (受影响的830排) 表“工作台”。扫描计数0,逻辑读取0,物理读取0, 预读读取0,lob逻辑读取0,lob物理读取0,lob预读读取0。 表“订单”。扫描计数1,逻辑读取21,物理读取1, 预读读取25,lob逻辑读取0,lob物理读取0,lob预读读取0。 表“客户”。扫描计数1,逻辑读取2,物理读取1, 预读读取0,lob逻辑读取0,lob物理读取0,lob预读读取0

对于第二个查询: (受影响的30排) 表“客户”。扫描计数0,逻辑读取60,物理读取1, 预读读取0,lob逻辑读取0,lob物理读取0,lob预读读取0。 表“订单”。扫描计数1,逻辑读取21,物理读取0,预读读取0, lob逻辑读取0,lob物理读取0,lob预读读取0

考虑到行的数量,为什么第二次查询中的
逻辑读取
多于第一次


对于第一个查询,可能可以使用索引,而对于第二个查询,可能不使用索引。 custid可以只是索引中包含的列,而不是键列。
您可以在执行计划中看到这一点。

对于第一个查询,可以使用索引,而对于第二个查询,则不能使用索引。 custid可以只是索引中包含的列,而不是键列。
您可以在执行计划中看到这一点。

无条件:

Table 'Customers'. Scan count 1, logical reads 2
条件是:

Table 'Customers'. Scan count 0, logical reads 60,
区别在于第一种情况下的扫描(速度很快,因为表很小)与通过索引进行的重复随机访问(速度不是很快,因为表太小,没有意义)

但请注意,所有这些由嵌套循环联接引起的重复逻辑读取不会导致实际的I/O(物理读取),因为它们会一次又一次地访问相同的几个块(这些块在缓冲区缓存工作集中)


这是否会导致性能问题?看起来查询已经足够快了。希望优化器能够在真正重要的情况下(即涉及大表的情况下)正确使用它。

没有条件:

Table 'Customers'. Scan count 1, logical reads 2
条件是:

Table 'Customers'. Scan count 0, logical reads 60,
区别在于第一种情况下的扫描(速度很快,因为表很小)与通过索引进行的重复随机访问(速度不是很快,因为表太小,没有意义)

但请注意,所有这些由嵌套循环联接引起的重复逻辑读取不会导致实际的I/O(物理读取),因为它们会一次又一次地访问相同的几个块(这些块在缓冲区缓存工作集中)


这是否会导致性能问题?看起来查询已经足够快了。希望优化器能够在真正重要的情况下(即涉及大表的情况下)正确使用它。

Merci,什么是工作表?这是用于收集连接数据的临时结构。第二个查询显然不需要它,因为这是通过索引访问直接拾取行。您可以为这两个查询附加执行计划。这应该会显示更多的细节。这里有:Hash Join(需要工作表)和Nested LoopMerci,什么是Worktable?这是用于收集连接数据的临时结构。第二个查询显然不需要它,因为这是通过索引访问直接拾取行。您可以为这两个查询附加执行计划。这应该会显示更多的细节。这里有:散列连接(需要工作表)和嵌套循环这很有趣。我将在OwenSQL安装中测试这一点。但现在,我要检查是否有销售索引。以custid为键、orderid和orderdate为包含列的订单这很有趣。我将在OwenSQL安装中测试这一点。但现在,我要检查Sales.Orders是否有索引,其中custid作为键,orderid和orderdate作为包含列