簡體   English   中英

SQL子查詢還是INNER-JOIN?

[英]SQL Sub-query or INNER-JOIN?

我有以下兩個問題:

declare @UserId as int
set @UserId = 1

-- Query #1: Sub-query
SELECT
    u.[Id] ,
    u.[Name] ,
    u.[OrgId] AS Organization,
    (SELECT o.[Name] FROM Org o WHERE o.Id = u.OrgId) As OrganizationName,
    [UserRoleId] AS UserRole,
    [UserCode] AS UserCode,
    [EmailAddress] As EmailAddress, 
    (SELECT SearchExpression FROM SearchCriteria WHERE UserId = @UserId AND IsDefault=1 ) AS SearchCriteria,
    (SELECT PageSize FROM UserPreferences WHERE UserId = @UserId) AS UserPreferencePageSize,
    (SELECT DrilldownPageSize FROM UserPreferences WHERE UserId = @UserId) AS UserPreferenceDrilldownPageSize
    FROM [User] as u
WHERE u.Id = @UserId

-- Query #2: LEFT OUTER JOIN-query
SELECT
    u.[Id] ,
    u.[Name] ,
    u.[OrgId] AS Organization,
    (SELECT o.[Name] FROM Org o WHERE o.Id = u.OrgId) As OrganizationName,
    [UserRoleId] AS UserRole,
    [UserCode] AS UserCode,
    [EmailAddress] As EmailAddress, 
    sc.SearchExpression As SearchExpression,
    up.PageSize As PageSize,
    up.DrilldownPageSize As DrilldownPageSize    
    FROM [User] as u
LEFT OUTER JOIN [UserPreferences] as up ON u.id = up.UserId
LEFT OUTER JOIN [SearchCriteria] as sc ON u.id = sc.UserId
    WHERE ISNULL(sc.IsDefault,1)=1 AND u.Id = @UserId

查詢執行計划統計信息:(相對於批處理的查詢成本)

  • 查詢#1(子查詢):56%
  • 查詢#2(加入):44%

我thot子查詢將是最佳的,因為子查詢將在應用WHERE過濾器后執行。 統計數據表明查詢#2 - JOIN方法更好。

請建議。 同樣作為一個溫和的SQL-Server用戶,我如何能夠更好地推導出哪個查詢(除了執行計划之外的任何其他內容,如果它更有用)

謝謝。

join比子查詢更快。

子查詢使繁忙的磁盤訪問,想到硬盤的讀寫指針(head?) ,它在訪問時來回傳遞:User,SearchExpression,PageSize,DrilldownPageSize,User,SearchExpression,PageSize,DrilldownPageSize,User ...等等上。

join通過將操作集中在前兩個表的結果上,任何后續連接都會集中連接到第一個連接表的內存(或緩存到磁盤)結果,依此類推。 較少的讀寫針運動,因此更快

你可以做的最好的事情是嘗試兩者並比較什么給你最好的表現。 很難再次猜測查詢優化器將執行什么操作(您可以編寫2個不同的查詢,這些查詢實際上最終會針對同一個執行計划進行優化)。

為了公平地比較性能,您應該確保通過在嘗試每個執行計划和數據緩存之前清除執行計划和數據緩存從級別競爭領域嘗試它們。 這可以使用以下命令完成,但只能在開發/測試數據庫服務器上執行此操作:

DBCC FREEPROCCACHE
DBCC DROPCLEANBUFFERS

我通常采用的方法是運行每個查詢3次,運行SQL事件探查器,這樣我就可以監視查詢的持續時間,讀取,CPU和寫入,然后我根據這些信息做出判斷。

例如
1)使用上述命令清除緩存
2)運行查詢和記錄統計信息
3)清除緩存
4)再次運行查詢
5)再次運行查詢(這將使用緩存的執行計划/數據)

然后重復第二個查詢進行比較。

它在很大程度上取決於數據的基數:如果你的內聯查找與join大量數據的開銷相比是最小的(當你只需要從該連接結果中提取一個小的子部分時),那么內聯選項會更快。 但是如果你在內聯選擇中有很大的開銷(即如果你的結果有很多行,而你正在為每一行調用一個內聯選擇),那么連接會更快。

我無法從你的問題中看到所涉及的數字(即多少行),因此很難做出定性評論。

例如,如果結果集有10行,則僅對這10行中的每一行執行內聯選擇,而連接可能涉及更多行,然后由WHERE子句選擇性地減少。 但是如果你有一個1000萬行的結果集,那么內聯選擇很可能會破壞性能,因為它是逐行的。

例子 :想象一下你必須從整個建築場地收集一堆磚(由大小等指定)並將它們塗成藍色。

內聯選擇 =選擇所需的所有磚塊,然后手工繪制。

join =將所有磚塊倒入一大桶油漆中,然后選擇你需要的油漆

如果你只想要10塊磚,那么選擇然后手工繪制要快得多。 如果你想要一百萬塊磚,那么首先在浴缸中進行大規模塗漆是可行的方法。

執行計划的相對成本並不總是可靠的績效指標。

我假設你的SQL只返回1行。 假設UserId是User上的唯一鍵,那么在大多數關系數據庫中,您的2種方法的性能將類似。

要記住的事情是:

  • 如果UserPreferences或SearchCriteria返回超過1行,第一種方法將引發sql錯誤,第二種方法將返回多於1行。
  • 第一種方法中明顯的額外查找(UserPreferences選擇兩次)沒有實際效果,因為對於第二次查找,記錄已經在緩沖區中
  • 如果由於某種原因User表被掃描表空間,第一種方法會快得多

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM