Sql 先过滤还是先加入?

Sql 先过滤还是先加入?,sql,sql-server,tsql,Sql,Sql Server,Tsql,我最初只是写了一个查询,以找出每个客户大于1的年度订单总数。 在1.query中,我过滤了结果集,并将其与另一个结果集连接起来,该结果集找到了客户名称。 奇怪的是,我猜filter first会产生更好的性能,因为需要加入的结果更少。所以我编写了第二个查询,先加入,然后过滤,这看起来比第一个查询更整洁。结果和我预期的一样,因为结果中的所有时间都较低。但我不知道什么时候最重要?或者这个案子只是巧合?如何看待绩效 use [AdventureWorks2012] set statistics tim

我最初只是写了一个查询,以找出每个客户大于1的年度订单总数。 在1.query中,我过滤了结果集,并将其与另一个结果集连接起来,该结果集找到了客户名称。 奇怪的是,我猜filter first会产生更好的性能,因为需要加入的结果更少。所以我编写了第二个查询,先加入,然后过滤,这看起来比第一个查询更整洁。结果和我预期的一样,因为结果中的所有时间都较低。但我不知道什么时候最重要?或者这个案子只是巧合?如何看待绩效

use [AdventureWorks2012]
set statistics time on;

--1.filter first,join second
select tempC.*,tempP.FirstName,tempP.LastName
from 
(select  Year(OrderDate) As OrderYear,CustomerID,count(CustomerID) As CustomerOrderAmt
from Sales.SalesOrderHeader 
group by Year(OrderDate),CustomerID 
having count(CustomerID) >1
) as tempC
join(
select p.FirstName,p.LastName,c.CustomerID
from Person.Person as p join Sales.Customer as c on c.PersonID=p.BusinessEntityID
) as tempP
on tempC.CustomerID=tempP.CustomerID
order by tempC.OrderYear,tempC.CustomerID
GO

--2.join first,filter second

select Year(so.OrderDate) As Orderdate,so.CustomerID,count(so.CustomerID) As CustomerOrderAmt,p.FirstName,p.LastName
from Sales.SalesOrderHeader as so
join Sales.Customer as C on so.CustomerID=c.CustomerID
join Person.Person as p on c.PersonID=p.BusinessEntityID
group by Year(so.OrderDate),so.CustomerID,p.FirstName,p.LastName
having count(so.CustomerID)>1
go

查询优化器可以选择以产生相同逻辑结果的任何顺序执行操作,因此,即使您尝试先筛选然后加入,除非您使用表变量或临时表强制执行,否则优化器也可能先加入然后加入筛选

如果您真的相信优化器在做一些愚蠢的事情,那么您可以尝试使用表var或temp表之类的方法,但是看起来愚蠢的东西实际上可能并不愚蠢,因为这些原因会变得非常高级


也就是说,有时编写查询的方式会影响优化器的工作,因此您通常应该查看执行计划。如果它们相同,则使用最清晰的代码。如果它们不进行测试和测试,并用最好的方式进行。

< P>我认为使用子查询可以减少连接操作的总数和块组中的列的数量。因此,我将立即告诉您,第一个查询肯定更高效

查询:

SELECT  
      t.OrderYear
    , t.CustomerID
    , t.CustomerOrderAmt 
    , p.FirstName 
    , p.LastName
FROM ( 
     SELECT 
            OrderYear = YEAR(OrderDate)  
          , CustomerID 
          , CustomerOrderAmt = COUNT(CustomerID) 
     FROM Sales.SalesOrderHeader
     GROUP BY 
            YEAR(OrderDate) 
          , CustomerID
     HAVING COUNT(CustomerID) > 1
) t
JOIN ( 
     SELECT   
            p.FirstName 
          , p.LastName 
          , c.CustomerID
     FROM Person.Person p
     JOIN Sales.Customer c ON c.PersonID = p.BusinessEntityID
) p ON t.CustomerID = p.CustomerID
ORDER BY 
       t.OrderYear 
     , t.CustomerID
-- first query
SQL Server Execution Times:
   CPU time = 94 ms,  elapsed time = 395 ms.

-- second query   
SQL Server Execution Times:
   CPU time = 140 ms,  elapsed time = 480 ms.
vs

查询成本:

SELECT  
      t.OrderYear
    , t.CustomerID
    , t.CustomerOrderAmt 
    , p.FirstName 
    , p.LastName
FROM ( 
     SELECT 
            OrderYear = YEAR(OrderDate)  
          , CustomerID 
          , CustomerOrderAmt = COUNT(CustomerID) 
     FROM Sales.SalesOrderHeader
     GROUP BY 
            YEAR(OrderDate) 
          , CustomerID
     HAVING COUNT(CustomerID) > 1
) t
JOIN ( 
     SELECT   
            p.FirstName 
          , p.LastName 
          , c.CustomerID
     FROM Person.Person p
     JOIN Sales.Customer c ON c.PersonID = p.BusinessEntityID
) p ON t.CustomerID = p.CustomerID
ORDER BY 
       t.OrderYear 
     , t.CustomerID
-- first query
SQL Server Execution Times:
   CPU time = 94 ms,  elapsed time = 395 ms.

-- second query   
SQL Server Execution Times:
   CPU time = 140 ms,  elapsed time = 480 ms.

执行时间:

SELECT  
      t.OrderYear
    , t.CustomerID
    , t.CustomerOrderAmt 
    , p.FirstName 
    , p.LastName
FROM ( 
     SELECT 
            OrderYear = YEAR(OrderDate)  
          , CustomerID 
          , CustomerOrderAmt = COUNT(CustomerID) 
     FROM Sales.SalesOrderHeader
     GROUP BY 
            YEAR(OrderDate) 
          , CustomerID
     HAVING COUNT(CustomerID) > 1
) t
JOIN ( 
     SELECT   
            p.FirstName 
          , p.LastName 
          , c.CustomerID
     FROM Person.Person p
     JOIN Sales.Customer c ON c.PersonID = p.BusinessEntityID
) p ON t.CustomerID = p.CustomerID
ORDER BY 
       t.OrderYear 
     , t.CustomerID
-- first query
SQL Server Execution Times:
   CPU time = 94 ms,  elapsed time = 395 ms.

-- second query   
SQL Server Execution Times:
   CPU time = 140 ms,  elapsed time = 480 ms.

您不必“猜测”性能,也不必依赖“巧合”。SQLServer为您提供了几种工具来获取有关查询执行方式的真实指标。客户端统计数据、执行计划、探查器跟踪、DMV和DMO就在我的脑海中。请注意,您的查询不是等价的,除非
(FirstName,LastName)
Person.Person表上的唯一键(在这种情况下,不应该是,您应该修复它)。感谢您的指导。接下来,我将介绍每个案例的执行计划