Database 实体框架-查询远程数据库时性能不佳

Database 实体框架-查询远程数据库时性能不佳,database,performance,entity-framework,Database,Performance,Entity Framework,我为我们的新项目评估了几种.NET数据库访问技术,发现在使用实体框架查询远程数据库时存在性能不良的行为。实体框架比LinqToSql或SqlClient慢10倍。也许你能帮我解释一下或者解决这个问题 测试参数: 数据库: SQL Server 2008企业版 一个表包含1000条记录 表结构: [dbo].[Master]( [Id] [int] IDENTITY(1,1) NOT NULL, [Value_Bit] [bit] NOT NULL, [

我为我们的新项目评估了几种.NET数据库访问技术,发现在使用实体框架查询远程数据库时存在性能不良的行为。实体框架比LinqToSql或SqlClient慢10倍。也许你能帮我解释一下或者解决这个问题

测试参数:

数据库:

  • SQL Server 2008企业版
  • 一个表包含1000条记录
  • 表结构:

    [dbo].[Master](
           [Id] [int] IDENTITY(1,1) NOT NULL,
           [Value_Bit] [bit] NOT NULL,
           [Value_Float] [float] NOT NULL,
           [Value_DateTime] [datetime2](7) NOT NULL,
           [Value_Uniqueidentifier] [uniqueidentifier] NOT NULL,
           [Value_NVarchar100] [nvarchar](100) NOT NULL,
           [Value_NVarchar1000] [nvarchar](1000) NOT NULL,
           [InsertDate] [datetime] NOT NULL,
           [UpdateDate] [datetime] NOT NULL,
           [Version] [timestamp] NOT NULL)
    
基准应用程序:

  • .NET Framework 4和4.5
  • 作为WinForms应用程序托管
数据库访问技术:

  • 实体框架5.0(RC)和4.3.1
  • LinqToSQL
  • SqlClient
计算机(客户端/服务器):

  • 三台硬件相似的不同计算机
  • A和B在同一子网中(例如192.168.1.1和192.168.1.2)
  • C与a和B位于不同的子网中(例如192.168.2.1)
我直接在不同的计算机(如客户机或服务器)上使用每种数据库访问技术执行sql查询
select*from Master
。平均时间是1000次迭代的结果

测试场景1:

  • 客户:A
  • 服务器:A

  • 实体框架:平均时间:17毫秒

  • LinqToSQL:平均时间:20毫秒
  • SqlClient:平均时间:15毫秒
测试场景2:

  • 客户:A
  • 服务器:B

  • 实体框架:平均时间:144毫秒

  • LinqToSQL:平均时间:141毫秒
  • SqlClient:平均时间:140毫秒
测试场景3:

  • 客户:A
  • 服务器:C

  • 实体框架:平均时间:2145毫秒

  • LinqToSQL:平均时间:151毫秒
  • SqlClient:平均时间:156毫秒
测试场景4:

  • 客户:B
  • 服务器:C

  • 实体框架:平均时间:2060毫秒

  • LinqToSQL:平均时间:141毫秒
  • SqlClient:平均时间:178毫秒
为什么测试场景3和4中的实体框架比LinqToSQL或SqlClient慢10倍

我用EntityFramework4.3.1、5(RC)和.NETFramework4和4.5对它进行了测试,每次都得到了相同的结果。我禁用了延迟加载和跟踪,使用了编译查询和预生成视图,但没有区别

我使用SQL探查器调查执行的SQL查询,发现实体框架的查询在SQL Server中已经花费了两秒钟(测试场景3)。如果我在计算机A上从ManagementStudio执行查询,只需100毫秒

我用dotTrace分析了我的基准测试应用程序(http://www.jetbrains.com)并发现,大部分执行时间都是由方法
ToList
消耗的。如果深入调用堆栈,我会看到方法
System.Data.SqlClient.SqlDataReader.GetString(Int32)
,最后是
sninitivemethodwrapper.SNIReadSyncOverAsync(SafeHandle,IntPtr&,Int32)
,它一直在使用。LinqToSql也使用SqlClient,并且几乎拥有相同的调用堆栈,但执行时间是10倍

我不知道引擎盖下发生了什么。也许这和计算机名解析有关,但我可以通过IP地址和计算机名ping计算机C。有没有人能解释这一点,或者对如何加快执行速度提出建议

提前谢谢


Mathias

问题分别大的时间间隔突然消失。我被告知管理员在网络上做了一些更改,因此我推断这与此有关,因为我在测试参数上没有做任何更改

不幸的是,我不知道他们发生了什么变化,我猜我永远也找不到答案。非常失望,因为我知道我不知道原因是什么


谢谢。

如果没有看到您的代码,很难给出任何有根据的猜测,但是EF有一些典型的东西,您可以大致了解一下

  • 通常,通过使用,您可以显著加快速度

  • 在查看代码时,EF查询的延迟执行可能是一个不明显的陷阱

一个常见的错误是执行返回IEnumerable或IQueryable集合的查询,然后在循环中使用该集合:

// Execution will be deferred:
IEnumerable<person> peopleList = objectContext.People.Where(item => item.ID > 100);
foreach (person somePerson in peopleList)
{
  // do something here
}
//执行将被推迟:
IEnumerable peopleList=objectContext.People.Where(item=>item.ID>100);
foreach(人员列表中的人员)
{
//在这里做点什么
}
这段代码将对数据库进行多次往返,这可能会导致严重的性能问题。Du延迟执行和延迟加载这将导致人员列表中每个项目的代码再次查询数据库。根据通过网络传输的数据量,仅此一项就可能对性能造成严重损害

只需对集合调用ToList()方法,就可以减少此开销。这将在一次往返中获取所有结果对象:

// Execution will be deferred:
List<person> peopleList = objectContext.People.Where(item => item.ID > 100)
                                              .ToList(); // Fetch objects NOW!
//执行将被推迟:
List peopleList=objectContext.People.Where(item=>item.ID>100)
.ToList();//现在取东西!
MSDN提供了一篇文章,其中包含一些建议:

提高绩效的策略 您可以提高整体性能 在实体框架中使用以下方法执行查询 战略

预生成视图

基于实体生成视图 模型是应用程序首次运行时的一项重要成本 执行查询。使用EdmGen.exe实用程序按以下方式预生成视图: 一个Visual Basic或C#代码文件,可在运行期间添加到项目中 设计。您也可以使用文本模板转换