LINQ查询非常慢-为什么
本文关键字:为什么 非常 查询 LINQ | 更新日期: 2023-09-27 18:04:42
我得到了一个非常简单的LINQ查询:
List<table> list = ( from t in ctx.table
where
t.test == someString
&& t.date >= dateStartInt
&& t.date <= dateEndInt
select t ).ToList<table>();
被查询的表大约有3000万行,但是test
和date
列被索引了。当它应该返回大约5000行时,需要几分钟才能完成。
我还检查了LINQ生成的SQL命令。如果我在SQL Server上运行该命令,则需要2秒才能完成。
这里LINQ有什么问题?这只是一个非常简单的查询,没有任何连接。
这是SQL Profiler显示的查询:
exec sp_executesql N'SELECT [t0].[test]
FROM [dbo].[table] AS [t0]
WHERE ([t0].[test] IN (@p0)) AND ([t0].[date] >= @p1)
AND ([t0].[date] <= @p2)',
N'@p0 nvarchar(12),@p1 int,@p2 int',@p0=N'123test',@p1=110801,@p2=110804
编辑:这真的很奇怪。在测试时,我注意到它现在快多了。现在LINQ查询大约20000行需要3秒,这是相当不错的。
更令人困惑的是:在我们的生产服务器上也是如此。一小时前它很慢,现在又快了。因为我是在开发服务器上进行测试的,所以我没有更改生产服务器上的任何内容。我能想到的唯一问题是这两个服务器都是虚拟化的,并且与许多其他服务器共享SAN。
我怎样才能知道问题出在哪里?
在责备LINQ之前,首先找出实际的延迟发生在哪里。
- 发送查询
- 查询执行
- 接收结果
- 将结果转换为本地类型 在UI中绑定/显示结果
- 以及与此进程相关的任何其他事件
然后开始责备LINQ;)
如果我不得不猜测,我会说"参数嗅探"是可能的,即它已经基于一个参数集构建并缓存了一个查询计划,这对于您当前的参数值来说是非常不理想的。您可以在常规TSQL中使用OPTION (OPTIMIZE FOR UNKNOWN)
来解决这个问题,但是没有LINQ-to-SQL/EF方法来暴露这个问题。
我的计划是:
- 使用分析来证明时间在查询中丢失了(与物化等相反)
- 一旦确认,考虑使用直接TSQL方法调用
例如,对于LINQ-to-SQL, ctx.ExecuteQuery<YourType>(tsql, arg0, ...)
可用于向服务器抛出原始TSQL(参数为{0}
等,如string.Format
)。就我个人而言,我倾向于"dapper"-非常相似的用法,但更快的物化器(但它不支持EntityRef<>
等延迟加载值-这通常是一件坏事,因为它导致N+1)。
。(整洁)
List<table> list = ctx.Query<table>(@"
select * from table
where test == @someString
and date >= @dateStartInt
and date <= @dateEndInt
OPTION (OPTIMIZE FOR UNKNOWN)",
new {someString, dateStartInt, dateEndInt}).ToList();
或(linq to sql):
List<table> list = ctx.ExecuteQuery<table>(@"
select * from table
where test == {0}
and date >= {1}
and date <= {2}
OPTION (OPTIMIZE FOR UNKNOWN)",
someString, dateStartInt, dateEndInt).ToList();