0

特定の都市とバナーでアクティブなショップをフィルタリングする次のクエリがあります

SELECT ShopName,CityName 
FROM Shop S INNER JOIN City C ON C.CityId=S.CityId
WHERE S.Active=1 AND S.Banner like '%res%'

SELECT ShopName,CityName 
FROM Shop S INNER JOIN City C ON C.CityId=S.CityId AND S.Active=1
WHERE S.Banner like '%res%'

両方のクエリを見ると、同じ結果が得られますが、異なる場所で S.Active を使用してください。1 つは IN JOIN で、もう 1 つは WHERE 句にあります。

どのクエリのパフォーマンスが向上しますか?

City テーブルには 3000000 の都市があり、Shops テーブルには 40000000 のショップがあります。(City,Active) に対して作成された非クラスター化インデックスがあります。

4

3 に答える 3

2

Conor Cunningham によって書かれたこのブログ投稿を読む必要があります: How to write non-JOIN WHERE clauses .

結合タイプがINNER[短い] answer の場合usually no。AdventureWorks データベース (SQL 2008) で次の 2 つのクエリを実行すると、次のようになります。

SET STATISTICS PROFILE ON
GO

SELECT  h.SalesOrderID, h.OrderDate, d.LineTotal
FROM    Sales.SalesOrderDetail d
INNER JOIN Sales.SalesOrderHeader h ON d.SalesOrderID = h.SalesOrderID
WHERE   h.OrderDate = '20010707'
AND     d.LineTotal < 100

SELECT  h.SalesOrderID, h.OrderDate, d.LineTotal
FROM    Sales.SalesOrderDetail d
INNER JOIN Sales.SalesOrderHeader h ON h.OrderDate = '20010707' AND d.SalesOrderID = h.SalesOrderID
WHERE   d.LineTotal < 100
GO

SET STATISTICS PROFILE OFF
GO

次に、これらの実行計画を取得します。

    Rows                 Executes             StmtText                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              StmtId      NodeId      Parent      PhysicalOp          
    -------------------- -------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------- ----------- ----------- --------------------
    5                    1                    SELECT    h.SalesOrderID, h.OrderDate, d.LineTotal
    FROM    Sales.SalesOrderDetail d
    INNER JOIN Sales.SalesOrderHeader h ON d.SalesOrderID = h.SalesOrderID
    WHERE   h.OrderDate = '20010707'
    AND     d.LineTotal < 100                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        1           1           0           NULL                           NULL                           NULL                                                                                                                                                                                 
    0                    0                      |--Compute Scalar(DEFINE:([d].[LineTotal]=[AdventureWorks2008].[Sales].[SalesOrderDetail].[LineTotal] as [d].[LineTotal]))                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1           2           1           Compute Scalar      
    5                    1                           |--Nested Loops(Inner Join, OUTER REFERENCES:([h].[SalesOrderID]))                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             1           3           2           Nested Loops        
    4                    1                                |--Index Seek(OBJECT:([AdventureWorks2008].[Sales].[SalesOrderHeader].[IX_SalesOrderHeader_OrderDate] AS [h]), SEEK:([h].[OrderDate]='2001-07-07 00:00:00.000') ORDERED FORWARD)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1           4           3           Index Seek          
    0                    0                                |--Compute Scalar(DEFINE:([d].[LineTotal]=isnull((CONVERT_IMPLICIT(numeric(19,4),[AdventureWorks2008].[Sales].[SalesOrderDetail].[UnitPrice] as [d].[UnitPrice],0)*((1.0)-CONVERT_IMPLICIT(numeric(19,4),[AdventureWorks2008].[Sales].[SalesOrderDetail].[UnitPriceDiscount] as [d].[UnitPriceDiscount],0)))*CONVERT_IMPLICIT(numeric(5,0),[AdventureWorks2008].[Sales].[SalesOrderDetail].[OrderQty] as [d].[OrderQty],0),(0.000000))))                                                                                                                                                                                                                                                                                                                                                                                                                                                                  1           5           3           Compute Scalar      
    5                    4                                     |--Clustered Index Seek(OBJECT:([AdventureWorks2008].[Sales].[SalesOrderDetail].[PK_SalesOrderDetail_SalesOrderID_SalesOrderDetailID] AS [d]), SEEK:([d].[SalesOrderID]=[AdventureWorks2008].[Sales].[SalesOrderHeader].[SalesOrderID] as [h].[SalesOrderID]),  WHERE:([AdventureWorks2008].[Sales].[SalesOrderDetail].[SalesOrderID] as [d].[SalesOrderID]>=(1) AND [AdventureWorks2008].[Sales].[SalesOrderDetail].[SalesOrderID] as [d].[SalesOrderID]<=(999999) AND isnull((CONVERT_IMPLICIT(numeric(19,4),[AdventureWorks2008].[Sales].[SalesOrderDetail].[UnitPrice] as [d].[UnitPrice],0)*((1.0)-CONVERT_IMPLICIT(numeric(19,4),[AdventureWorks2008].[Sales].[SalesOrderDetail].[UnitPriceDiscount] as [d].[UnitPriceDiscount],0)))*CONVERT_IMPLICIT(numeric(5,0),[AdventureWorks2008].[Sales].[SalesOrderDetail].[OrderQty] as [d].[OrderQty],0),(0.000000))<(100.000000)) ORDERED FORWARD)  1           6           5           Clustered Index Seek

and

Rows                 Executes             StmtText                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              StmtId      NodeId      Parent      PhysicalOp          
-------------------- -------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------- ----------- ----------- --------------------
5                    1                    SELECT    h.SalesOrderID, h.OrderDate, d.LineTotal
FROM    Sales.SalesOrderDetail d
INNER JOIN Sales.SalesOrderHeader h ON h.OrderDate = '20010707' AND d.SalesOrderID = h.SalesOrderID
WHERE   d.LineTotal < 100                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1           1           0           NULL                           NULL                           NULL                                                                                                                                                                               
0                    0                      |--Compute Scalar(DEFINE:([d].[LineTotal]=[AdventureWorks2008].[Sales].[SalesOrderDetail].[LineTotal] as [d].[LineTotal]))                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1           2           1           Compute Scalar      
5                    1                           |--Nested Loops(Inner Join, OUTER REFERENCES:([h].[SalesOrderID]))                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             1           3           2           Nested Loops        
4                    1                                |--Index Seek(OBJECT:([AdventureWorks2008].[Sales].[SalesOrderHeader].[IX_SalesOrderHeader_OrderDate] AS [h]), SEEK:([h].[OrderDate]='2001-07-07 00:00:00.000') ORDERED FORWARD)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1           4           3           Index Seek          
0                    0                                |--Compute Scalar(DEFINE:([d].[LineTotal]=isnull((CONVERT_IMPLICIT(numeric(19,4),[AdventureWorks2008].[Sales].[SalesOrderDetail].[UnitPrice] as [d].[UnitPrice],0)*((1.0)-CONVERT_IMPLICIT(numeric(19,4),[AdventureWorks2008].[Sales].[SalesOrderDetail].[UnitPriceDiscount] as [d].[UnitPriceDiscount],0)))*CONVERT_IMPLICIT(numeric(5,0),[AdventureWorks2008].[Sales].[SalesOrderDetail].[OrderQty] as [d].[OrderQty],0),(0.000000))))                                                                                                                                                                                                                                                                                                                                                                                                                                                                  1           5           3           Compute Scalar      
5                    4                                     |--Clustered Index Seek(OBJECT:([AdventureWorks2008].[Sales].[SalesOrderDetail].[PK_SalesOrderDetail_SalesOrderID_SalesOrderDetailID] AS [d]), SEEK:([d].[SalesOrderID]=[AdventureWorks2008].[Sales].[SalesOrderHeader].[SalesOrderID] as [h].[SalesOrderID]),  WHERE:([AdventureWorks2008].[Sales].[SalesOrderDetail].[SalesOrderID] as [d].[SalesOrderID]>=(1) AND [AdventureWorks2008].[Sales].[SalesOrderDetail].[SalesOrderID] as [d].[SalesOrderID]<=(999999) AND isnull((CONVERT_IMPLICIT(numeric(19,4),[AdventureWorks2008].[Sales].[SalesOrderDetail].[UnitPrice] as [d].[UnitPrice],0)*((1.0)-CONVERT_IMPLICIT(numeric(19,4),[AdventureWorks2008].[Sales].[SalesOrderDetail].[UnitPriceDiscount] as [d].[UnitPriceDiscount],0)))*CONVERT_IMPLICIT(numeric(5,0),[AdventureWorks2008].[Sales].[SalesOrderDetail].[OrderQty] as [d].[OrderQty],0),(0.000000))<(100.000000)) ORDERED FORWARD)  1           6           5           Clustered Index Seek

これらのプランを WinMerge と比較すると、違いがわかります。 ここに画像の説明を入力

NodeId=1(最終結果セットを表す最終ステップ)についてSELECT ...は、SQL ステートメントが異なるため、違いが生じます。ただし、前の手順 ( NodeId=2..6) には がありますno differences

注 1 : 奇妙なケース ( ANSI_NULSS ON/OFF) では、diff が発生する場合があります。結果と差分。実行計画:

SET ANSI_NULLS ON;

SELECT  *
FROM    (VALUES (1,100),(2,200),(3,NULL)) AS Customer(CustomerID,Limit)
INNER JOIN (VALUES (11,1),(12,1),(13,2),(14,3)) AS [Order](OrderID,CustomerID) 
ON      Customer.CustomerID=[Order].CustomerID 
AND     Customer.Limit=NULL

SET ANSI_NULLS OFF;

SELECT  *
FROM    (VALUES (1,100),(2,200),(3,NULL)) AS Customer(CustomerID,Limit)
INNER JOIN (VALUES (11,1),(12,1),(13,2),(14,3)) AS [Order](OrderID,CustomerID) 
ON      Customer.CustomerID=[Order].CustomerID 
WHERE   Customer.Limit=NULL

SET ANSI_NULLS ON;

結果:

CustomerID  Limit       OrderID     CustomerID
----------- ----------- ----------- -----------
(0 row(s) affected)

CustomerID  Limit       OrderID     CustomerID
----------- ----------- ----------- -----------
3           NULL        14          3
(1 row(s) affected)

ここに画像の説明を入力

注 2 :ANSI_NULLS設定は常に行う必要がありますON

于 2013-02-24T07:14:14.967 に答える
0

どちらがより優れたパフォーマンスを発揮するかについて強調しないでください。SQL は PROCEDURAL 言語ではなく DECLARATIVE であることを理解する必要があります。簡単に言えば、クエリはクエリ オプティマイザーによって実行される実際のコードに変換されます。すべての可能性において、それはまったく同じです。

確かに知るためにクエリプランを見ることができますが、それらが異なっていたとしても、この種の時期尚早な最適化は時間の無駄です. クエリを作成する前ではなく、問題があることがわかっているときに最適化します。

于 2013-02-24T07:06:22.830 に答える
0

それらは同じですが、JOIN にある必要があります。

昔は、JOIN に ON がないため、結合は WHERE にありました。しかし、ANSI は JOIN に ON を導入し、最新の SQL エンジンは自動的に WHERE を ON に変換します。

あなたのシナリオでは、重要なのは C.CityId にインデックスがあることです

于 2013-02-24T06:48:54.000 に答える