如何修复此linq查询的性能问题
本文关键字:性能 问题 查询 linq 何修复 | 更新日期: 2023-09-27 18:27:34
下面的C#代码在3秒内执行。我还列出了SQL事件探查器的输出。如果我将语句更改为不使用动态SQL,它将在几毫秒内执行。我找不到任何好的资源来解决这个问题。但我找到了一篇文章,解释了在DynamicSQL中,由于解析器不知道参数的值,因此无法优化查询计划。
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查询
您是否将该查询粘贴到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();
LINQ看起来不错,你有正确的索引吗?
在您粘贴的来自SSMS的查询中,它没有对DISTRICT_CD进行任何限制,因此请确保这实际上是正在运行的查询。
您的性能问题在"CompareTo"部分。此函数无法转换为常规SQL,因此Entity框架将首先实现与前两个条件匹配的所有对象(使用纯SQL获取)。在这之后(正如你所看到的,whitch需要一些时间),第三个条件在内存中匹配。在linq查询中避免使用CompareTo方法,这样问题就会迎刃而解。