SQL INNER JOIN与存在性能考虑的位置

时间:2017-03-15 11:36:31

标签: sql sql-server performance linq join

假设我有一个从客户端发送的字符串列表,在本例中是区域。我有一张名为Compliance Regions的表格。我想搜索具有name属性的行,并且该行应该存在region项。

在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]  

cregions

并且

--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]
    )

cregions2 根据要求添加了执行计划。

3 个答案:

答案 0 :(得分:2)

考虑到两种选择,第二种可能更好,因为列名没有函数调用。

然而,两者并不相同。第一个进行部分匹配,第二个进行完全匹配。你应该真的做那个你想做的事。性能仅次于准确性。

两者都是痛苦的看。将CHARINDEX()的输出转换为索引?我们可以说&#34;冗余&#34;?

他们质疑为什么查询不简单:

select . . .
from [Administration].[ComplianceRegions] AS [Extent1]
where Extent1.Name in (N'Canada', N'EN 50530');

这是此逻辑中最简单,性能最佳的版本。

答案 1 :(得分:0)

@JNK的行情回答in this post

EXISTS用于返回布尔值,JOIN返回整个其他表

EXISTS仅用于测试子查询是否返回结果,并且一旦发生短路就会发生短路。 JOIN用于通过将结果集与来自另一个具有关系的表中的其他字段进行组合来扩展结果集。

在您的示例中,查询在语义上是等效的。

通常,在以下情况下使用EXISTS:

您不需要从相关表中返回数据 您在相关表中有欺骗(如果重复值,JOIN可能会导致重复的行) 你想检查存在(使用而不是LEFT OUTER JOIN ... NULL条件) 如果您有适当的索引,则大多数时间EXISTS将与JOIN执行相同的操作。例外情况是非常复杂的子查询,通常使用EXISTS会更快。

如果您的JOIN键未编入索引,则使用EXISTS可能会更快,但您需要根据具体情况进行测试。

JOIN语法更容易阅读,也更正常。

答案 2 :(得分:0)

这些查询是平等的。两者都很糟糕,我不会选择其中任何一个。它们具有硬编码值,因此无法重复使用。我不确定sql server autoparametrization是否可以处理它,因此执行计划缓存可能会受到影响。正确的解决方案是使用表值参数,遗憾的是,据我所知,linq提供程序不支持它们。所以你必须自己进行查询,你只能使用linq来实现结果。

您可以尝试Ivan Stoev提供的解决方案,它有多好取决于您的提供商生产的产品。 Linq2sql对于较长的列表不能很好地扩展,因为它产生的参数与列表中的许多项一样多。当列表中的项目数相同时,至少可以重用执行计划。