entity framework太慢。 我有什么select?

我遵循了“不要过早优化”的口号,并使用entity framework对我的WCF服务进行了编码。

但是,我分析了性能,entity framework太慢了。 (我的应用程序在大约1.2秒内处理2条消息,其中我正在重写的(遗留)应用程序在同一时间内会同时处理5-6条消息(传统应用程序会调用sprocs来访问其数据库)。

我的分析指出entity framework占用了每条消息的大部分时间。

那么,我有什么select?

  • 那里有更好的ORM吗?
    (支持正常读写对象的东西,速度很快..)

  • 有没有办法让entity framework更快?
    注意 :当我说得更快的时候,我的意思是说,从长远来看,不是第一个电话(第一个电话很慢(15秒),但这不是问题,我只需要快点就可以了的消息。)

  • 一些神秘的第三选项,将帮助我更快地从我的服务中获得。

注意:我的大部分数据库交互或创build和更新。 我做了很less的select和删除。

您应该首先分析entity framework实际发布的SQL命令。 根据您的configuration(POCO,自我跟踪实体),有很多优化空间。 您可以使用ObjectSet<T>.ToTraceString()方法debuggingSQL命令(在debugging模式和发行模式之间不应该有所不同ObjectSet<T>.ToTraceString() 。 如果遇到需要进一步优化的查询,可以使用一些投影来为EF提供更多关于您想要完成的信息。

例:

 Product product = db.Products.SingleOrDefault(p => p.Id == 10); // executes SELECT * FROM Products WHERE Id = 10 ProductDto dto = new ProductDto(); foreach (Category category in product.Categories) // executes SELECT * FROM Categories WHERE ProductId = 10 { dto.Categories.Add(new CategoryDto { Name = category.Name }); } 

可以replace为:

 var query = from p in db.Products where p.Id == 10 select new { p.Name, Categories = from c in p.Categories select c.Name }; ProductDto dto = new ProductDto(); foreach (var categoryName in query.Single().Categories) // Executes SELECT p.Id, c.Name FROM Products as p, Categories as c WHERE p.Id = 10 AND p.Id = c.ProductId { dto.Categories.Add(new CategoryDto { Name = categoryName }); } 

我只是把它input到了脑海中,所以这并不是如何执行的,但是如果你把所有你知道的查询都告诉了它,EF实际上会做一些很好的优化(在这种情况下,我们需要类别 – 名)。 但是这不像急切加载(db.Products.Include(“Categories”)),因为投影可以进一步减less要加载的数据量。

事实上,像Entity Framework这样的产品总是会变得缓慢而低效,因为它们正在执行更多的代码。

我也觉得很愚蠢的是,人们build议应该优化LINQ查询,查看生成的SQL,使用debugging器,预编译,采取许多额外的步骤等,即浪费大量时间。 没有人说 – 简化! 每个人都想通过采取更多步骤来进一步纠结(浪费时间)。

一个常识的方法是根本不使用EF或LINQ。 使用普通的SQL。 这没有什么错。 只是因为程序员之间存在一种心态,他们觉得每个新产品都有使用的冲动,并不意味着它是好的或者是可行的。 大多数程序员认为,如果他们整合了一家大公司发布的每一个新代码,就会使他们成为一个更聪明的程序员; 根本不是真的。 智能编程主要是关于如何以更less的头痛,不确定性和最less的时间做更多的事情。 记住 – 时间! 这是最重要的元素,所以尽量find方法不要浪费它在解决糟糕/膨胀代码中的问题,只是为了符合一些所谓的“模式”

放松,享受生活,rest一下,停止使用额外的function,代码,产品,“模式”。 生命短暂,代码的寿命更短,当然不是火箭科学。 删除像LINQ,EF和其他图层,你的代码将会有效地运行,可扩展,是的,它仍然很容易维护。 太多的抽象是一个糟糕的“模式”。

这是解决您的问题。

一个build议是只使用LINQ to Entity Framework作为单条logging的CRUD语句。

对于更多涉及的查询,search,报告等,编写存储过程并将其添加到entity framework模型,如MSDN上所述 。

这是我用我的几个网站采取的方法,它似乎是生产力和性能之间的一个很好的妥协。 entity framework并不总是为当前的任务生成最有效的SQL。 而不是花时间去弄清楚为什么,为更复杂的查询编写存储过程实际上为我节省了时间。 一旦你熟悉了这个过程,把存储过程添加到你的EF模型并不是太麻烦。 当然,将它添加到你的模型的好处是,你可以得到所有使用ORM的强types的好处。

如果您纯粹获取数据,那么当您告知EF不跟踪它获取的实体时,对性能有很大的帮助。 通过使用MergeOption.NoTracking执行此操作。 EF只会生成查询,执行并将结果反序列化为对象,但不会试图跟踪实体更改或任何此类性质。 如果一个查询很简单(不花太多时间等待数据库返回),我发现将它设置为NoTracking可以使查询性能翻一番。

请参阅关于MergeOption枚举的MSDN文章:

身份parsing,状态pipe理和变更跟踪

这似乎是一个关于EF性能的好文章:

性能和entity framework

你说你已经分析了应用程序。 你是否也分析了ORM? Ayende有一个EF分析器,它将突出您可以优化您的EF代码的位置。 你可以在这里find它:

http://efprof.com/

请记住,如果您需要获得性能,则可以在ORM旁边使用传统的SQL方法。

如果有更快/更好的ORM? 根据您的对象/数据模型,您可以考虑使用微型ORM之一,例如Dapper , Massive或PetaPoco 。

Dapper网站发布了一些比较基准,可以让你知道他们如何与其他ORM进行比较。 但值得注意的是,微型ORM不支持EF和NH等完整ORM的丰富function集。

你可能想看看RavenDB 。 这是一个非关系数据库(来自Ayende),可以让你直接存储POCO而不需要映射 。 RavenDB针对读取进行了优化,通过消除操作模式和将对象映射到该模式的需求,使开发人员的生活变得更加简单。 但是请注意,这是使用ORM方法的一种截然不同的方法,这些方法在产品的网站中进行了概述。

我在@Slaumafind了答案,对于加快速度非常有用。 我对插入和更新都使用了相同的模式,而且性能也有所提高。

从我的经验来看,问题不是EF,而是ORM方法本身。

一般来说,所有ORM都会遇到N + 1问题,而不是最优化的查询等。我最好的猜测是跟踪导致性能下降的查询,并尝试调整ORM工具,或者用SPROC重写那些部分。

只有在您完成configuration之后进行优化才有意义。 如果您发现数据库访问速度缓慢,则可以转换为使用存储过程并保留EF。 如果你发现EF本身很慢,你可能不得不切换到不同的ORM或根本不使用ORM。

这是一个简单的非框架,非ORM选项,以每秒10,000次的速度加载30个字段。 在旧笔记本电脑上运行,可能比在真实环境中快。

https://sourceforge.net/projects/dopersistence/?source=directory

我也遇到了这个问题。 我讨厌在英孚转储,因为它工作得很好,但它只是缓慢。 在大多数情况下,我只是想find一个logging或更新/插入。 即使这样简单的操作也很慢。 我从表中将1100条logging从列表中拉回到列表中,并且该操作花费了6秒钟的时间。 对我来说这太长了,即使节约也需要很长时间。

我结束了自己的ORM。 我从数据库中提取了相同的1100条logging,而我的ORM花费了2秒,比EF快得多。 所有与我的ORM几乎是即时的。 目前唯一的限制是它只能用于MS SQL Server,但是可以改变它与Oracle之类的其他工作。 我现在所有的东西都使用MS SQL Server。

如果你想尝试我的ORM这里是链接和网站:

https://github.com/jdemeuse1204/OR-M-Data-Entities

或者,如果你想使用块:

PM> Install-Package OR-M_DataEntities

文档也在那里

entity framework本身不应该造成重大瓶颈。 有可能是其他原因。 您可以尝试将EF切换到Linq2SQL,两者都具有比较function,代码应该很容易转换,但在很多情况下,Linq2SQL比EF快。

我们有一个类似的应用程序(WCF – > EF – >数据库),每秒120个请求很容易,所以我非常确定EF不是你的问题在这里,据说,我已经看到编译查询主要性能的改善。

我用EF,LINQ to SQL和Dapper。 小巧是最快的。 例如:我需要1000个主logging,每个logging有4个子logging。 我用LINQ到SQL,它花了大约6秒钟。 然后,我切换到精简,从单个存储过程中检索到2个logging集,并为每个logging添加了子logging。 总时间1秒。

另外存储过程使用了交叉应用的表值函数,我发现标量值函数很慢。

我的build议是使用EF或LINQ到SQL,并在某些情况下切换到精简。