[英]SQL INNER JOIN vs Where Exists Performance Consideration
假設我有一個從客戶端發送的字符串列表,在這種情況下是區域。 我有一個名為Compliance Regions的表。 我要搜索具有名稱屬性的行,並且該行上應該存在區域項目。
在LINQ中,我可以通過兩種不同的方式來實現。 像下面一樣,它們產生兩個不同的SQL查詢。 我的問題是應該選擇哪個? 哪個查詢的性能更好?
List<string> regions = new List<string>() { "Canada", "EN 50530" };
var cregions = from c in complianceRegions
from r in regions
where c.Name.Equals(r)
select c;
var cregions2 = from c in complianceRegions
where regions.Any(x => x == c.Name)
select c;
生成的sql如下所示。
-- cregions
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name],
[Extent1].[Description] AS [Description]
FROM [Administration].[ComplianceRegions] AS [Extent1]
INNER JOIN (SELECT
N'Canada' AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable1]
UNION ALL
SELECT
N'EN 50530' AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable2]) AS [UnionAll1] ON [Extent1].[Name] = [UnionAll1].[C1]
和
--cregions2
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name],
[Extent1].[Description] AS [Description]
FROM [Administration].[ComplianceRegions] AS [Extent1]
WHERE EXISTS (SELECT
1 AS [C1]
FROM (SELECT
N'Canada' AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable1]
UNION ALL
SELECT
N'EN 50530' AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable2]) AS [UnionAll1]
WHERE [UnionAll1].[C1] = [Extent1].[Name]
)
給定這兩種選擇,第二種可能更好,因為在列名上沒有函數調用。
但是,兩者並不相同。 第一個進行部分匹配,第二個進行完全匹配。 您應該真正按照自己的意願去做。 性能次於准確性。
兩者都很痛苦。 是否將CHARINDEX()
的輸出轉換為索引? 我們可以說“冗余”嗎?
他們提出了一個問題,為什么查詢不簡單:
select . . .
from [Administration].[ComplianceRegions] AS [Extent1]
where Extent1.Name in (N'Canada', N'EN 50530');
這是此邏輯的最簡單且性能最佳的版本。
引用@JNK 在這篇文章中的答案。
EXISTS用於返回布爾值,JOIN返回整個其他表
EXISTS僅用於測試子查詢是否返回結果,並在發生短路后立即對其進行短路。 JOIN用於通過將結果集與另一個有關系的表中的其他字段組合來擴展結果集。
在您的示例中,查詢在語義上是等效的。
通常,在以下情況下使用EXISTS:
您不需要從相關表返回數據您在相關表中有重復項(如果重復值,JOIN會導致重復的行)您要檢查是否存在(使用而不是LEFT OUTER JOIN ... NULL條件)具有適當的索引,大多數情況下,EXISTS的性能與JOIN相同。 例外是非常復雜的子查詢,通常使用EXISTS更快。
如果未為JOIN鍵建立索引,則使用EXISTS可能會更快,但是您需要針對特定情況進行測試。
JOIN語法通常更易於閱讀和清除。
這些查詢是相等的。 而且兩者都很糟糕,我不會選擇其中任何一個。 它們具有硬編碼的值,因此不能重復使用。 我不確定sql server autoparametrization是否可以解決該問題,因此執行計划緩存可能會受到影響。 正確的解決方案是使用表值參數,不幸的是,據我所知,linq提供程序不支持它們。 因此,您將不得不自行查詢,您只能使用linq來實現結果。
您可以嘗試Ivan Stoev提供的解決方案,其效果取決於您的提供商提供的產品。 Linq2sql不適用於較長的列表,因為它產生的參數與列表中的所有項目一樣多。 當列表中的項目數相同時,至少可以重用執行計划。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.