SQL點滴之with語句和子查詢的效能比較

來源:互聯網
上載者:User

之前筆者和大家分享了《使用with語句來寫一個稍微複雜sql語句》,這一次筆者針對with語句和子查詢做了一個效能的比較。

在博友SingleCat的提醒下,對with語句做一些效能測試,這裡使用的測試載入器是SQL Server Profile。我選擇了最後一個語句,因為這個語句比較複雜一點。開始的時候單獨執行一次發現他們的差別不大,就差幾個毫秒,後來想讓他們多執行幾次,連續執行10

次看看執行的結果。下面貼出測試用的語句。

 
  1. /*with查詢*/  
  2. declare @withquery varchar(5000)  
  3. declare @execcount int=0  
  4. set @withquery='with TheseEmployees as(  
  5. select empid from hr.employees where country=N''USA''),  
  6. CharacteristicFunctions as(  
  7. select custid,  
  8.        case when custid in (select custid from sales.orders as o where o.empid=e.empid) then 1 else 0 end as charfun  
  9. from sales.customers as c cross join TheseEmployees as e)  
  10. select custid from CharacteristicFunctions group by custid having min(charfun)=1 order by custid  
  11. '  
  12. while @execcount<10  
  13. begin 
  14. exec (@withquery);  
  15. set @execcount=@execcount+1  
  16. end 
  17.  
  18. /*子查詢*/  
  19. declare @subquery varchar(5000)  
  20. declare @execcount int=0  
  21. set @subquery='select custid from Sales.Orders where empid in 
  22. (select empid from HR.Employees where country = N''USA'') group by custid  
  23. having count(distinct empid)=(select count(*) from HR.Employees where country = N''USA'');  
  24. '  
  25. while @execcount<10  
  26. begin 
  27. exec (@subquery);  
  28. set @execcount=@execcount+1  
  29. end 

從SQL Server Profile中如下

可以看到子查詢語句的執行時間要少於with語句,我覺得主要是with查詢中有一個cross join做了笛卡爾積的關係,於是又實驗了上面的那個簡單一點的,下面是測試語句。

 
  1. /*with語句*/  
  2. declare @withquery varchar(5000)  
  3. declare @execcount int=0  
  4. set @withquery='with c(orderyear,custid) as(  
  5. select YEAR(orderdate),custid from sales.orders)  
  6. select orderyear,COUNT(distinct(custid)) numCusts from c group by c.orderyear'   
  7. while @execcount<100  
  8. begin 
  9. exec (@withquery);  
  10. set @execcount=@execcount+1  
  11. end 
  12.  
  13. /*子查詢*/  
  14. declare @subquery varchar(5000)  
  15. declare @execcount int=0  
  16. set @subquery='select orderyear,COUNT(distinct(custid)) numCusts  
  17. from (select YEAR(orderdate),custid from sales.orders) as D(orderyear,custid)  
  18. group by orderyear'  
  19. while @execcount<100  
  20. begin 
  21. exec (@subquery);  
  22. set @execcount=@execcount+1  
  23. end 

這次做10次查詢還是沒有多大的差距,with語句用10個duration,子查詢用了11個,有時候還會翻過來。於是把執行次數改成100,這次還是子查詢使用的時間要少,如下

最終結論,子查詢好比with語句效率高。

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.