与SSMS相比,LINQ查询非常慢

本文关键字:查询 非常 LINQ SSMS 相比 | 更新日期: 2023-09-27 18:03:25

主要问题是否有一些已知的限制,混乱,配置问题,任何东西,可以解释这样一个事实,即在所有条件相同的情况下,从c# linq运行的查询可能比以任何其他方式运行的查询要长一个数量级?

是linq中的缩写查询。这是视图和表之间非常直接的连接。

var query = (
    from content in context.ApprovedContentView
                where content.BucketId == 13098 && content.ContentTypeId == 5220 
    join item in context.ActiveContent
                on content.ContentId equals item.ItemId
        where
                item.IsSuchAndSuch == true && item.SomeOtherProperty == 5000 
        select new 
        {
            ItemId = item.ItemId,
            Title = item.Title,
            SubTitle = item.SubTitle,
            DescriptionText = item.DescriptionText,
            /* about 10 other scalar fields */
        });
int count = query.Count();
var data = query.OrderByDescending(item => item.ItemId).Skip(5).Take(3);

下面是它生成的(缩写/格式化)SQL

SELECT 
[GroupBy1].[A1] AS [C1]
FROM ( SELECT 
    COUNT(1) AS [A1]
    FROM       [SchemaX].[ApprovedContentView] AS [Extent1]
    INNER JOIN [SchemaX].[ActiveContent] AS [Extent2] ON [Extent1].[ContentId] = [Extent2].[ItemId]
    WHERE (13098 = [Extent1].[BucketId]) AND (5220 = [Extent1].[ContentTypeId ]) AND 
    (1 = [Extent2].[IsSuchAndSuch]) AND (5000 = [Extent2].[SomeOtherProperty ])
)  AS [GroupBy1]
GO
SELECT TOP (3) 
[Filter1].[BucketId] AS [BucketId], 
[Filter1].[ItemId] AS [ItemId], 
[Filter1].[Title] AS [Title], 
[Filter1].[SubTitle] AS [SubTitle], 
[Filter1].[DescriptionText] AS [DescriptionText], 
/* other fields */
FROM ( SELECT 
            [Extent1].[BucketId] AS [BucketId], 
            [Extent2].[ItemId] AS [ItemId], 
            [Extent2].[Title] AS [Title], 
            [Extent2].[SubTitle] AS [SubTitle], 
            [Extent2].[DescriptionText] AS [DescriptionText], 
            /* other fields */
            row_number() OVER (ORDER BY [Extent2].[DealId] DESC) AS [row_number]
    FROM  [SchemaX].[ApprovedContentView] AS [Extent1]
    INNER JOIN [SchemaX].[ActiveContent] AS [Extent2] ON [Extent1].[ContentId] = [Extent2].[ItemId]
    WHERE (13098 = [Extent1].[BucketId]) AND (5220 = [Extent1].[ContentTypeId ]) AND 
            (1 = [Extent2].[IsSuchAndSuch]) AND (5000 = [Extent2].[SomeOtherProperty ])
)  AS [Filter1]
WHERE [Filter1].[row_number] > 5
ORDER BY [Filter1].[DealId] DESC

不同的场景我的速度测试基于使用SQL profiler

观察查询运行情况。原位

当这个linq查询在我的c#应用程序中作为正常操作的一部分执行时,我观察到在SQL profiler中,选择计数需要整整3秒才能完成,奇怪的是,产生投影的查询只需要200毫秒,并且时间是可重复的,这似乎排除了查询执行计划缓存问题。(运行实体框架5,SQL server 2008 r2)

在LINQPAD

当我使用c#应用程序的dll数据上下文通过LinqPad执行linq语句时,计数和投影分别在四分之一秒内完成(~224ms,总运行时间为~450ms)。

在ssm

无论sql的来源如何,当我复制sql配置文件报告执行的实际代码并将其粘贴到管理工作室窗口并执行时,大约需要224ms。

数据库调优在SSMS中,当我计算从分析器(从代码或从linqpad)复制的sql的实际执行计划时,我发现sql使用了所有正确的索引,并且只报告索引查找——没有表扫描,没有rid查找。

那么,发生了什么?有人见过这样的东西吗?

与SSMS相比,LINQ查询非常慢

我会确保您没有为应用程序缓存的糟糕执行计划。当我在一个已经在使用的数据库上进行模式工作时,这种情况经常发生。很有可能,由于模式更改,为应用程序执行上下文缓存的执行计划效率低下,而为SSMS查询生成的执行计划是最新的,并且没有发现这些性能问题。

我会尝试使用DBCC FREEPROCCACHE来强制更新您的执行计划,看看是否解决了这个问题。

ARITHABORT在SSMS中默认为ON,在SqlClient连接中默认为OFF。

如果问题再次出现,添加:

new SqlCommand("SET ARITHABORT ON", connection).ExecuteNonQuery();