Linq声明运行得很慢

时间:2014-02-20 03:12:46

标签: c# sql linq linq-to-entities

我有以下linq语句,运行速度很慢(我看到3秒钟)

var results = 
    from pi in ProductItems.Include("Parent")
    join nt in PicklistDetails 
        on pi.Diameter.PicklistCode + "-" + pi.Schedule.PicklistCode 
        equals nt.PicklistCode
    where pi.Active 
    select new
    {
        Active = pi.Active,
        ID = pi.ID,
        IsCategory = pi.IsCategory,
        Name = pi.Name,
        Diameter = pi.Diameter.Value1,
        Thickness = nt.Value1,
        ThicknessCode = pi.Diameter.PicklistCode + "-" + pi.Schedule.PicklistCode
    };    
results.Dump();

我可以直接在SQL中编写一个等效的语句,它运行得更快。有人能告诉我是否有更有效的方法来编写linq查询?

更新:感谢所有回复到目前为止这里有更多信息。上面的linq查询生成的sql如下所示:

SELECT 
[Extent1].[ID] AS [ID], 
[Extent1].[Active] AS [Active], 
[Extent1].[IsCategory] AS [IsCategory], 
[Extent1].[Name] AS [Name], 
[Extent7].[Value1] AS [Value1], 
[Extent2].[Value1] AS [Value11], 
[Extent7].[PicklistCode] + N'-' + [Extent8].[PicklistCode] AS [C1]
FROM    [dbo].[ProductItem] AS [Extent1]
INNER JOIN [dbo].[PicklistDetails] AS [Extent2] ON  EXISTS (SELECT 
    1 AS [C1]
    FROM      ( SELECT 1 AS X ) AS [SingleRowTable1]
    LEFT OUTER JOIN  (SELECT 
        [Extent3].[ID] AS [ID], 
        [Extent3].[PicklistCode] AS [PicklistCode]
        FROM [dbo].[PicklistDetails] AS [Extent3]
        WHERE [Extent1].[DiameterID] = [Extent3].[ID] ) AS [Project1] ON 1 = 1
    LEFT OUTER JOIN  (SELECT 
        [Extent4].[ID] AS [ID], 
        [Extent4].[PicklistCode] AS [PicklistCode]
        FROM [dbo].[PicklistDetails] AS [Extent4]
        WHERE [Extent1].[ScheduleID] = [Extent4].[ID] ) AS [Project2] ON 1 = 1
    LEFT OUTER JOIN  (SELECT 
        [Extent5].[ID] AS [ID], 
        [Extent5].[PicklistCode] AS [PicklistCode]
        FROM [dbo].[PicklistDetails] AS [Extent5]
        WHERE [Extent1].[DiameterID] = [Extent5].[ID] ) AS [Project3] ON 1 = 1
    LEFT OUTER JOIN  (SELECT 
        [Extent6].[ID] AS [ID], 
        [Extent6].[PicklistCode] AS [PicklistCode]
        FROM [dbo].[PicklistDetails] AS [Extent6]
        WHERE [Extent1].[ScheduleID] = [Extent6].[ID] ) AS [Project4] ON 1 = 1
    WHERE (([Project1].[PicklistCode] + N'-' + [Project2].[PicklistCode]) = [Extent2].[PicklistCode]) OR (([Project3].[PicklistCode] + N'-' + [Project4].[PicklistCode] IS NULL) AND ([Extent2].[PicklistCode] IS NULL))
)
LEFT OUTER JOIN [dbo].[PicklistDetails] AS [Extent7] ON [Extent1].[DiameterID] = [Extent7].[ID]
LEFT OUTER JOIN [dbo].[PicklistDetails] AS [Extent8] ON [Extent1].[ScheduleID] = [Extent8].[ID]
WHERE [Extent1].[Active] = 1

使用此查询,我可以更快地在sql中获得相同的结果:

select pi.Active, pi.id, pi.IsCategory, pi.Name, diameter.Value1 as diameter, nt.Value1 as thickness, diameter.PicklistCode + '-' + schedule.PicklistCode as thicknesscode
from ProductItem pi
    inner join PicklistDetails diameter on diameter.id = pi.DiameterID
    inner join PicklistDetails schedule on schedule.id = pi.ScheduleID
    inner join PicklistDetails nt on nt.PicklistCode = diameter.PicklistCode + '-' + schedule.PicklistCode
where pi.Active = 1

我知道我可以直接运行这个sql查询,但我想知道我是否可以让linq查询运行得更快。正如我所提到的,linq查询运行大约3秒,而sql查询以1秒的速度运行。

我检查了执行计划,两个主要项目如下 41%排序([ProductItem] .DiameterID Ascending,[ProductItem] .ScheduleID Ascending,[PicklistDetails] .PicklistCode Ascending) 49%行数盘管(惰性线轴)我不完全确定这是什么。

2 个答案:

答案 0 :(得分:1)

如果您不知道正确使用它,

Linq to entities可能会非常慢。以下提示可以真正改善您的表现:

1.避免将所有数据库对象放入一个单一实体模型

2。)如果不需要,禁用实体的更改跟踪

3.。)使用预生成视图减少第一次请求的响应时间

4.。)如果不需要,请避免获取所有字段

5.。)选择适当的数据处理集合

6.。)在需要的地方使用编译查询

7.)仅检索所需的记录数

8。)避免使用Contains

其中第2点和第5点非常重要。之后你也可以考虑8,7和休息。您始终可以使用ToTraceString()检查linq查询向数据库发送的内容。它会给你等效的sql查询,可以分析和提高性能。您可以参考以下链接了解更多详情:

[link] http://www.dotnet-tricks.com/Tutorial/entityframework/J8bO140912-Tips-to-improve-Entity-Framework-Performance.html

答案 1 :(得分:1)

我怀疑这里的罪魁祸首是你的计算连接值,特别是从两个单独的表(Diameter和Schedule)中提取值时。 SQL无法很好地利用其索引结构。根据生成的SQL检查该连接的执行计划。最后,我最好的建议是通过对计算出的选项列表代码进行非规范化并将其放在productitem表中来删除查询计算,但是不能很好地了解您的数据模型以了解是否有意义。