107

我看到一些非常奇怪的性能与使用 .NET 框架版本 4 的实体框架代码优先的非常简单的查询相关。LINQ2Entities 查询如下所示:

 context.MyTables.Where(m => m.SomeStringProp == stringVar);

这需要超过 3000 毫秒才能执行。生成的 SQL 看起来很简单:

 SELECT [Extent1].[ID], [Extent1].[SomeStringProp], [Extent1].[SomeOtherProp],
 ...
 FROM [MyTable] as [Extent1]
 WHERE [Extent1].[SomeStringProp] = '1234567890'

此查询在通过 Management Studio 运行时几乎立即运行。当我更改 C# 代码以使用 SqlQuery 函数时,它会在 5-10 毫秒内运行:

 context.MyTables.SqlQuery("SELECT [Extent1].[ID] ... WHERE [Extent1].[SomeStringProp] = @param", stringVar);

因此,完全相同的 SQL,在这两种情况下都对生成的实体进行了更改跟踪,但两者之间的性能差异很大。是什么赋予了?

4

6 回答 6

116

找到了。事实证明这是 SQL 数据类型的问题。数据库中的SomeStringProp列是 varchar,但 EF 假定 .NET 字符串类型是 nvarchar。在查询数据库进行比较期间产生的翻译过程需要很长时间。我认为 EF Prof 在这里让我误入歧途,正在运行的查询的更准确表示如下:

 SELECT [Extent1].[ID], [Extent1].[SomeStringProp], [Extent1].[SomeOtherProp],
 ...
 FROM [MyTable] as [Extent1]
 WHERE [Extent1].[SomeStringProp] = N'1234567890'

所以最终的修复是注释代码优先模型,指示正确的 SQL 数据类型:

public class MyTable
{
    ...

    [Column(TypeName="varchar")]
    public string SomeStringProp { get; set; }

    ...
}
于 2013-04-02T19:39:05.030 回答
52

减慢我的 EF 查询的原因是将不可为空的标量与可空的标量进行比较:

long? userId = 10; // nullable scalar

db.Table<Document>().Where(x => x.User.Id == userId).ToList() // or userId.Value
                                ^^^^^^^^^    ^^^^^^
                                Type: long   Type: long?

该查询耗时 35 秒。但是一个小的重构如下:

long? userId = 10;
long userIdValue = userId.Value;

db.Table<Document>().Where(x => x.User.Id == userIdValue).ToList()
                                ^^^^^^^^^    ^^^^^^^^^^^
                                Type: long   Type: long

给出了令人难以置信的结果:只需 50 毫秒即可完成。它看起来像 EF 中的一个错误。

于 2014-11-14T13:14:32.677 回答
12

如果您使用的是 fluent 映射,则可以将IsUnicode(false)其用作配置的一部分以获得相同的效果 -

http://msdn.microsoft.com/en-us/data/jj591617.aspx#1.9

http://msdn.microsoft.com/en-us/library/gg696416%28v=vs.103%29.aspx

于 2013-07-10T10:38:19.900 回答
4

我遇到了同样的问题(从 SQL 管理器执行时查询很快)但是从 EF 执行时超时到期。

原来实体(从视图创建)有错误的实体键。所以实体有相同键的重复行,我猜它必须在后台进行分组。

于 2013-04-12T18:01:28.260 回答
3

我也遇到了一个复杂的 ef 查询。对我来说,将 6 秒 ef 查询减少到它生成的亚秒 sql 查询的一个修复方法是关闭延迟加载。

要找到此设置 (ef 6),请转到 .edmx 文件并查看属性 -> 代码生成 -> 启用延迟加载。设置为假。

对我来说性能有了很大的提高。

于 2014-05-30T11:40:14.333 回答
3

我也有这个问题。事实证明,我的罪魁祸首是 SQL-Server parameter sniffing

我的问题实际上是由于参数嗅探引起的第一个线索是,使用“set arithabort off”或“set arithabort on”运行查询会在 Management Studio 中产生截然不同的执行时间。这是因为 ADO.NET 默认使用“set arithabort off”,而 Management Studio 默认使用“set arithabort on”。查询计划缓存根据此参数保留不同的计划。

我禁用了查询的查询计划缓存,您可以在此处找到解决方案。

于 2017-11-20T14:41:54.170 回答