Sql-Server

過濾加入條件和性能

  • December 12, 2020

我有以下類型的查詢:

SELECT *
FROM CUSTOMER C
JOIN USERTABLE U on C.AccountmanagerID = US.ID

user 表也有外部使用者,這些使用者永遠不能是 accountmanager。該表有大約 30k 條記錄,其中只有大約 500 個使用者可以是 accountmanager。我可以根據使用者名的長度過濾它們。僅返回 1k 條記錄。

SELECT *
FROM CUSTOMER C
JOIN USERTABLE U on C.AccountmanagerID = US.ID
AND len(U.USERNAME) = 3

當我執行查詢計劃時,第二個查詢計劃效率更高,我可以想像,但我找不到任何完整的理由。有人可以啟發我並給我一些背景資訊。我也想知道這是否總是如此,或者這只是巧合。

查詢計劃連結: https ://www.brentozar.com/pastetheplan/?id=HypDy3MnP

提前致謝

不同之處在於您的第二個Execution Plan是在您的 Customer 表上使用 Index Seek (這通常是一個性能更高的操作):

執行計劃

這是因為您的附加過濾器會導致 acardinality返回更少的記錄,並使Index Seek操作比Index Scan. 請注意第一個執行計劃和第二個執行計劃中箭頭之間的粗細差異。JOIN由於第二個查詢的謂詞有助於預先過濾數據,因此第二個計劃中返回的行數要少得多。

這也導致JOIN對兩者Tables一起使用更有效的操作,使用Nested Loops運算符而不是Merge Join.

要回答您的最後一個問題,這既不是巧合,也不是總是如此,Execution Plans而且 SQL 引擎在後台所做的工作相當複雜,因此測試和比較計劃和結果是了解正在發生的事情的最佳方式,因為推測對於給定的場景是困難的,並且從一個場景到下一個場景都不同。

在這種情況下,它剛剛發現您選擇的過濾器預先從 User 表中減少了足夠的記錄,INNER JOIN到 Customer 表要小得多,並允許它使用Index Seek性能更高的操作(並且再次導致JOIN操作也是一種更有效的東西,一種Nested Loops操作)。

當您在“OSUSR_6VB_MSS_CUSTOMER”中突出顯示操作時JOIN,您可以通過查看“估計行數”(在這種情況下,您應該使用Actual Execution Plan而不是Estimated Execution Plan盡可能)屬性來查看客戶表中記錄的減少。Index Scan第一個Execution PlanIndex Seek第二個中的操作Execution Plan相比,從 31,877 行變為大約 472 行:

執行計劃 1

執行計劃 2

引用自:https://dba.stackexchange.com/questions/281413