子查询,连接查询,在SQL2008R2中性能如何?

以前或多或少的听说过,能用子查询的地方改用连接查询,性能有提升,如下的伪代码

select *  from tab1 where col1 in (select col1 from tab2)
select * from tab1 inner join tab2 on tab1.col1=tab2.col2

这种使用连接查询代替子查询的写法,据说在SQL2000中有效果,我没有测试过,这次测试一下在SQL2008R2中的性能如何?

首先看看独立子查询的逻辑读:

SET STATISTICS IO ON;

USE AdventureWorks
GO

DBCC FREEPROCCACHE
CHECKPOINT
DBCC DROPCLEANBUFFERS


SELECT count(*) FROM sales.SalesOrderHeader AS soh
WHERE soh.SalesOrderID IN
                        (
                            SELECT SalesOrderID FROM sales.salesOrderDetail AS sod
                            WHERE OrderQty>1
                            AND sod.ProductID IN
                            (
                                SELECT ProductID FROM Production.product AS p
                                WHERE p.color=N'red'
                            )
                        )
    

这段代码的逻辑读为:

(1 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 'SalesOrderHeader'. Scan count 1, logical reads 45, physical reads 2, read-ahead reads 43, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'SalesOrderDetail'. Scan count 1, logical reads 1238, physical reads 35, read-ahead reads 1233, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Product'. Scan count 1, logical reads 15, physical reads 4, read-ahead reads 20, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

再来看看使用连接查询的逻辑读:

DBCC FREEPROCCACHE
CHECKPOINT
DBCC DROPCLEANBUFFERS

SELECT count(DISTINCT soh.salesorderid)
FROM sales.salesorderheader AS soh
JOIN sales.salesorderdetail AS sod
ON soh.salesorderid=sod.salesorderid
AND sod.orderqty>1
JOIN production.product AS p ON
sod.productid=p.productid
AND p.color=N'red'

这段代码的逻辑读为:

(1 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 'SalesOrderHeader'. Scan count 1, logical reads 45, physical reads 2, read-ahead reads 43, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'SalesOrderDetail'. Scan count 1, logical reads 1238, physical reads 35, read-ahead reads 1233, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Product'. Scan count 1, logical reads 15, physical reads 4, read-ahead reads 20, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

另外看看连接查询的第二种写法,把color=N’red'放入where 子句中

DBCC FREEPROCCACHE
CHECKPOINT
DBCC DROPCLEANBUFFERS

SELECT count(DISTINCT soh.salesorderid)
FROM sales.salesorderheader AS soh
JOIN sales.salesorderdetail AS sod
ON soh.salesorderid=sod.salesorderid
AND sod.orderqty>1
JOIN production.product AS p 
ON sod.productid=p.productid
WHERE p.color=N'red'

这段代码的逻辑读为:

(1 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 'SalesOrderHeader'. Scan count 1, logical reads 45, physical reads 2, read-ahead reads 43, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'SalesOrderDetail'. Scan count 1, logical reads 1238, physical reads 34, read-ahead reads 1233, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Product'. Scan count 1, logical reads 15, physical reads 4, read-ahead reads 20, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

可以看到这三段代码的逻辑读是一样的,性能上没有任何的区别,看看从上到下三段代码的执行计划:

image

从上可以得到的结论:

1:SQLSERVER引擎优化器已足够聪明,知道这三种写法没有任何的区别,所以大家怎么写还是按照自己的习惯来

2:对于查询是这样,对于UPDATE/DELETE也是如此,子查询和连接查询在SQL2008中没有任何的区别!!

原文地址:https://www.cnblogs.com/fly_zj/p/2633970.html