我为我们的新项目评估了几种 .NET 数据库访问技术,并发现使用 Entity Framework 查询远程数据库时性能不佳。Entity Framework 比 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 框架 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)
select * from Master
我在作为客户端或服务器的不同计算机上直接使用每种数据库访问技术执行 sql 查询。平均时间是 1000 次迭代的结果。
测试场景一:
- 客户:A
服务器:A
实体框架:平均时间:17 毫秒
- LinqToSQL:平均时间:20 毫秒
- SqlClient:平均时间:15 毫秒
测试场景二:
- 客户:A
服务器:B
实体框架:平均时间:144 毫秒
- LinqToSQL:平均时间:141 毫秒
- SqlClient:平均时间:140 毫秒
测试场景 3:
- 客户:A
服务器:C
实体框架:平均时间:2145 毫秒
- LinqToSQL:平均时间:151 毫秒
- SqlClient:平均时间:156 毫秒
测试场景4:
- 客户:乙
服务器:C
实体框架:平均时间:2060 毫秒
- LinqToSQL:平均时间:141 毫秒
- SqlClient:平均时间:178 毫秒
为什么测试场景 3 和 4 中的实体框架比 LinqToSQL 或 SqlClient 慢 10 倍?
我在 Entity Framework 4.3.1、5 (RC) 和 .NET Framework 4 和 4.5 下对其进行了测试,每次都得到相同的结果。我禁用了延迟加载和跟踪,使用编译查询和预生成视图,但没有区别。
我使用 SQL Profiler 调查执行的 SQL 查询,发现实体框架的查询在 SQL Server 中已经花费了两秒钟(测试场景 3)。如果我从计算机 A 上的 Management Studio 执行查询,只需要 100 毫秒。
我使用 dotTrace (http://www.jetbrains.com) 分析了我的基准应用程序,发现大部分执行时间都被方法消耗掉了ToList
。如果我深入调用堆栈,我会看到该方法System.Data.SqlClient.SqlDataReader.GetString(Int32)
,最后SNINativeMethodWrapper.SNIReadSyncOverAsync(SafeHandle, IntPtr&, Int32)
会一直消耗。LinqToSql 也使用了 SqlClient,调用栈几乎一样,但是执行时间快了 10 倍。
我不知道引擎盖下发生了什么。也许它与计算机名称解析有关,但我可以通过 IP 地址及其计算机名称 ping 计算机 C。有没有人可以解释或建议如何加快执行速度?
提前致谢
马蒂亚斯