实体框架查询速度慢,但SqlQuery中的SQL速度相同

Bri*_*van 83 performance entity-framework ef-code-first

我看到一些与使用.NET框架版本4的Entity Framework Code-First的非常简单的查询相关的一些非常奇怪的性能.LINQ2Entities查询如下所示:

 context.MyTables.Where(m => m.SomeStringProp == stringVar);
Run Code Online (Sandbox Code Playgroud)

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

 SELECT [Extent1].[ID], [Extent1].[SomeStringProp], [Extent1].[SomeOtherProp],
 ...
 FROM [MyTable] as [Extent1]
 WHERE [Extent1].[SomeStringProp] = '1234567890'
Run Code Online (Sandbox Code Playgroud)

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

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

因此,完全相同的SQL,在两种情况下都会对结果实体进行更改跟踪,但两者之间存在差异.是什么赋予了?

Bri*_*van 83

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

 SELECT [Extent1].[ID], [Extent1].[SomeStringProp], [Extent1].[SomeOtherProp],
 ...
 FROM [MyTable] as [Extent1]
 WHERE [Extent1].[SomeStringProp] = N'1234567890'
Run Code Online (Sandbox Code Playgroud)

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

public class MyTable
{
    ...

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

    ...
}
Run Code Online (Sandbox Code Playgroud)


cry*_*yss 39

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

long? userId = 10; // nullable scalar

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

该查询耗时35秒.但是像这样的微小重构:

long? userId = 10;
long userIdValue = userId.Value; // I've done that only for the presentation pursposes

db.Table<Document>().Where(x => x.User.Id == userIdValue).ToList()
                                ^^^^^^^^^    ^^^^^^^^^^^
                                Type: long   Type: long
Run Code Online (Sandbox Code Playgroud)

给出了惊人的结果.完成只用了50ms.它可能是EF中的一个错误.

  • 这太奇怪了 (11认同)
  • EF Core 中也存在同样的问题。感谢您找到这个! (2认同)

Mat*_*att 7

如果您使用的是流畅的映射,则可以将其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