2011-07-17 345 views
40

我正在使用CROSS APPLY加入用戶和GeoPhone表,並且一切工作都很快,但現在我在Phone列中擁有NULL值的用戶。交叉應用在最終輸出中跳過這些行。所以我切換到了OUTER APPLY。但是它的工作速度要慢得多(當輸出中的總行數增加1000時,速度要慢15倍以上)。CROSS APPLY vs OUTER APPLY速度差

SELECT TOP (10000) dbo.Users.Login, dbo.Users.Phone, GeoPhone.Country 
FROM dbo.Users CROSS APPLY 
       (SELECT TOP 1 Country 
       FROM dbo.GeoPhone 
       WHERE dbo.Users.Phone <= dbo.GeoPhone.[End]) GeoPhone 

對戰:

SELECT TOP (10000) dbo.Users.Login, dbo.Users.Phone, GeoPhone.Country 
FROM dbo.Users OUTER APPLY 
       (SELECT TOP 1 Country 
       FROM dbo.GeoPhone 
       WHERE dbo.Users.Phone <= dbo.GeoPhone.[End]) GeoPhone 

我試圖理解爲什麼。正如我看到的執行計劃是不同的。但理論上我看不到任何可能導致這種放緩的計算。

任何想法?

我最後的解決方案:

SELECT TOP (10000) dbo.Users.Login, dbo.Users.Phone, GeoPhone.Country 
FROM dbo.Users CROSS APPLY 
       (SELECT TOP 1 Country 
       FROM dbo.GeoPhone 
       WHERE ISNULL(dbo.Users.Phone, 0) <= dbo.GeoPhone.[End]) GeoPhone 

這實際分配爲國家非空電話和國家從第一範圍空手機(這是我的情況「未知」的話)。由於某種原因WHERE dbo.Users.Phone <= dbo.GeoPhone.[End] OR dbo.Users.Phone IS NULL做了相同的結果,但速度較慢。

請隨時對此發表評論。

回答

57

CROSS APPLY是MSSQL專用... Microsoft on APPLY

APPLY原因右側的查詢在左側的查詢結果,每執行一次。 CROSS只考慮像INNER JOIN這樣的匹配行。使用OUTER考慮左側查詢中的所有行。多餘的行受到傷害。

我建議你重新制定你的右側查詢來顯式接受NULL而不是使用OUTER APPLY。

+2

謝謝Magicianeer,你的消息後,我試圖重新制定右側的查詢,發現快速的解決方案。我將它添加到第一條消息。 – Denis

9

你可以試試這個:

SELECT TOP (10000) dbo.Users.Login, dbo.Users.Phone, GeoPhone.Country 
FROM dbo.Users CROSS APPLY 
       (SELECT TOP 1 Country 
       FROM dbo.GeoPhone 
       WHERE dbo.Users.Phone <= dbo.GeoPhone.[End]) GeoPhone 
UNION ALL 
SELECT TOP (10000) dbo.Users.Login, dbo.Users.Phone, NULL AS Country 
FROM dbo.Users 
WHERE dbo.Users.Phone IS NULL 

確保您在dbo.Users.Phone有一個索引

+0

這工作速度很快!但我發現稍快一點的解決方案。我將它添加到我的問題。 – Denis