entity framework与存储过程 – 性能测量
我试图build立多lessentity framework超过存储过程。 我希望说服我的老板让我们使用entity framework,以方便开发。
问题是我跑了一个性能testing,看起来EF比存储过程慢大约7倍。 我觉得这很难相信,我想知道如果我错过了什么。 这是一个确定的testing? 我能做些什么来提高EF Test的性能吗?
var queries = 10000; // Stored Proc Test Stopwatch spStopwatch = new Stopwatch(); spStopwatch.Start(); for (int i = 0; i < queries; i++ ) { using (var sqlConn = new SlxDbConnection().Connection) { var cmd = new SqlCommand("uspSearchPerformanceTest", sqlConn) { CommandType = CommandType.StoredProcedure }; cmd.Parameters.AddWithValue("@searchText", "gstrader"); sqlConn.Open(); SqlDataReader dr = cmd.ExecuteReader(); List<User> users = new List<User>(); while (dr.Read()) { users.Add(new User { IsAnonymous = Convert.ToBoolean(dr["IsAnonymous"]), LastActivityDate = Convert.ToDateTime(dr["LastActivityDate"]), LoweredUserName = dr["LoweredUserName"].ToString(), MobileAlias = dr["MobileAlias"].ToString(), UserId = new Guid(dr["UserId"].ToString()), UserName = (dr["UserName"]).ToString() }); } var username = users.First().UserName; sqlConn.Close(); } } spStopwatch.Stop(); Console.WriteLine("SP - {0} Queries took {1}", queries, spStopwatch.ElapsedMilliseconds ); // EF Test Stopwatch entityStopWatch = new Stopwatch(); var context = new SlxDbContext(); var userSet = context.Set<User>(); entityStopWatch.Start(); for (int i = 0; i < queries; i++) { User user = userSet.Where(x => x.UserName == "gstrader").First(); } entityStopWatch.Stop(); Console.WriteLine("Entity - {0} Queries took {1}", queries, entityStopWatch.ElapsedMilliseconds);
结果:
SP – 10000查询花了2278
实体 – 10000查询花了16277
有一些事情可以做,以优化您的查询。 在MSDN上你可以find一个很好的概述。
但说实话,手动映射的存储过程在性能上总是会更快。 但问问自己,performance有多重要? 在大多数项目中,开发时间比性能更重要。 什么是更难以发展? 具有parsing或entity framework查询的原始查询?
ORMs的devise并不是因为它比手写方法performance得好得多。 我们使用它们是因为开发更容易!
如果您使用Entity Framework编写应用程序,并将所有查询隐藏在存储库模式后面,则可以快速开发,然后当性能成为问题时,衡量您的应用程序以检测瓶颈。 那么也许你的一些查询需要优化,可以移动到存储过程和手动映射。
与@Wouter de Kort一致…此外,当您需要移动到程序时,您可以将EF与程序配合使用,以协助从一个移植到另一个移植。
如果您将function统一到精心devise的程序中,则在典型应用程序中移动到过程将会更快。 即尽可能在一次存储过程中完成尽可能多的工作。 例如,在购物车MVC应用程序中,当用户点击退房button时, 可以使用ORM类似于:
- 查看用户的身份validation(login仍然有效吗?)
- 查阅权限(他们可以购买上述物品吗?是否有特殊要求?)
- 查看库存数量,以确保它们没有被耗尽
- 写入数据库以在付款前保留(从可用库存中移除)项目
- 查看付款信息
- 伐木…?
或者它可能是完全不同的步骤,但无论如何,重点是,MVC应用程序将使用ORM对数据库进行多次调用以进入下一步。
如果所有这些逻辑都被封装在一个写得很好的sproc中,那么只需要一次调用sproc就完成了。 使用MVC-ORM路由,必须将数据从数据库复制到驱动程序,然后传递给ORM(通常通过networking传输到不同的主机),然后由MVC应用程序读取,然后重复一个简单的决策,直到所有步骤完成。 在使用封装了检出步骤的sproc的情况下,数据复制和移动要less得多,networkingIOless,上下文切换less等。
这样思考MVC-ORM解决scheme。 人“A”只是对事实的了解,而“B”人则具有以他没有提出的事实做决定的精明。 人“B”电子邮件“A”的事实。 根据“A”的答案,“B”在作出决定之前可能会要求更多的事实。 这是很多来回消息。
如果你有一个人拥有所有的事实和知识作出决定,你只需要提出一个问题,他们的大脑就会在内部处理所有事情,以得出答案。 不涉及与他人的审议。 自然会更快。
这并不是说它必然会更好 。 将事实从决定中分离出来意味着这些组件可以单独更换/testing,但是,如果您已经与MVC和数据库结婚,那么这是一个“非问题”。
另一方面,许多MVC粉丝不喜欢编写SQL,因此他们认为将任何决策逻辑放入SQL中是一种自然灾害。 对于这样的人来说,用MVC使用的相同语言编写任何逻辑是非常必要的,因为它加快了开发速度。 在某些情况下,这也是一个“非问题”,因为对于某些RDMBS,您可以使用与MVC使用的语言相同的语言编写sprocs(例如:.Net – SQL Server sprocs可以用C#编写并使用.Net; PostgreSQL的函数(不用sprocs)可以用Perl,Python,PHP等编写)这种情况下的优点是你可以用一个调用封装多个步骤的快速sprocs,你可以使用一种编程语言在编码方面已经很快了。