如何修复此linq查询的性能问题?

时间:2012-03-13 15:03:30

标签: c# linq entity-framework sql-server-2005

以下C#代码在3秒内执行。我也列出了SQL Profiler输出。如果我将语句更改为不使用动态SQL,则会在几毫秒内执行。我找不到任何好的资源来解决这个问题。但是我能够找到一篇文章来解释动态SQL,因为解析器不知道参数的值,它无法优化查询计划。

public string GetIncorporation(Parcel parcel)
    {

    var result = (from c in _context.Districts
                  where c.PARCEL_ID == parcel.PARCEL_ID && c.DB_YEAR == parcel.DB_YEAR && c.DISTRICT_CD.CompareTo("9000") < 0
                  select c).ToList();

    exec sp_executesql N'SELECT 
[GroupBy1].[A1] AS [C1]
FROM ( SELECT 
    MAX([Filter1].[A1]) AS [A1]
    FROM ( SELECT 
        SUBSTRING([Extent1].[DISTRICT_CD], 0 + 1, 2) + N''00'' AS [A1]
        FROM [STAGE].[DISTRICT] AS [Extent1]
        WHERE ([Extent1].[PARCEL_ID] = @p__linq__0) AND ([Extent1].[DB_YEAR] = @p__linq__1) AND ([Extent1].[DISTRICT_CD] < N''9000'')
    )  AS [Filter1]
)  AS [GroupBy1]',N'@p__linq__0 nvarchar(4000),@p__linq__1 int',@p__linq__0=N'0001-02-0003',@p__linq__1=2012

我正在尝试构建服务层。我不希望有一批混合的存储过程和Linq查询

3 个答案:

答案 0 :(得分:4)

您是否在SSMS中粘贴了该查询,运行执行计划,并查看是否建议丢失任何索引?

此外,如果您不需要表中的所有列,请使用select:

限制它们
var result = (from c in _context.Districts
                  where c.PARCEL_ID == parcel.PARCEL_ID && c.DB_YEAR == parcel.DB_YEAR && c.DISTRICT_CD.CompareTo("9000") < 0
                  select c.Parcel_ID).ToList();

var result = (from c in _context.Districts
                  where c.PARCEL_ID == parcel.PARCEL_ID && c.DB_YEAR == parcel.DB_YEAR && c.DISTRICT_CD.CompareTo("9000") < 0
                  select new { c.Parcel_ID, c.column2, c.column3}).ToList();

答案 1 :(得分:0)

LINQ看起来很好,你有正确的索引吗?

在您粘贴的SSMS查询中,它没有对DISTRICT_CD进行任何限制,因此请确保它实际上是正在运行的查询。

答案 2 :(得分:0)

您的性能问题出现在'CompareTo'部分。此函数无法转换为常规SQL,因此实体框架将首先实现与前两个条件匹配的所有对象(使用纯SQL获取)。在此之后(如你所见,花费一些时间),第三个条件在内存中匹配。避免在你的linq查询中使用CompareTo方法,你的问题就会消失。