为啥实体框架在直接选择语句中的执行速度比 Dapper 快 [关闭]

     2023-04-12     43

关键词:

【中文标题】为啥实体框架在直接选择语句中的执行速度比 Dapper 快 [关闭]【英文标题】:Why Entity Framework performs faster than Dapper in direct select statement [closed]为什么实体框架在直接选择语句中的执行速度比 Dapper 快 [关闭] 【发布时间】:2017-04-23 10:06:56 【问题描述】:

我是使用 ORM 处理数据库的新手,目前我正在制作一个新项目,我必须决定是否使用实体框架或 Dapper。我读过很多文章说 Dapper 比 Entity Framework 快。

所以我做了 2 个简单的原型项目,一个使用 Dapper,另一个使用 Entity Framework 和一个函数来从一张表中获取所有行。 表架构如下图

两个项目的代码如下

用于 Dapper 项目

System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
IEnumerable<Emp> emplist = cn.Query<Emp>(@"Select * From Employees");
sw.Stop();
MessageBox.Show(sw.ElapsedMilliseconds.ToString());

对于实体框架项目

System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
IEnumerable<Employee> emplist = hrctx.Employees.ToList();
sw.Stop();
MessageBox.Show(sw.ElapsedMilliseconds.ToString());

仅在我第一次运行项目时多次尝试上述代码后,dapper 代码会更快,并且在第一次之后,我总是从实体框架项目中获得更好的结果 我还在实体框架项目上尝试了以下语句来停止延迟加载

hrctx.Configuration.LazyLoadingEnabled = false;

但除第一次外,相同的 EF 执行速度更快。

任何人都可以给我解释或指导是什么让 EF 在这个示例中更快,尽管网络上的所有文章都说相反

更新

我已将实体示例中的代码行更改为

IEnumerable<Employee> emplist = hrctx.Employees.AsNoTracking().ToList();

使用某些文章中提到的 AsNoTracking 会停止实体框架缓存,并且在停止缓存后,dapper 示例的性能会更好,(但差别不大)

【问题讨论】:

这不是一个基准测试...您只是在测试一个 非常 基本场景,其中 EF 恰好更快,因为它没有很多事情要做。在实际场景中,您可能会发现 Dapper 更快(因为它只做一件事:将查询结果映射到对象),但您必须编写更多代码来做同样的事情。 您应该尝试真实场景,包括连接、过滤器、分组、更新、插入等 当您使用几个连接进行查询时,您将开始注意到巨大的性能差异,一旦 ef 需要编译您的查询,您将获得性能影响 我很久以前做了一些测试,发现 EF 在返回少量行时始终更快。我仍然不确定为什么会这样,但我猜我认为 EF 可能会在默认设置上做更好的连接管理。在映射方面,我认为 EF 和 dapper 之间没有显着的性能差异,但是,如果您想要对查询进行边缘性能调整,那么您无法使用 LINQ ORM 做一些事情。我的(旧)文章在这里:blog.staticvoid.co.nz/2012/3/24/… 这种测试没用。您应该测试很多操作(所有 CRUD)并使用真正的 ORM,而不是 dapper。 Linq2db 有一些精巧的高级功能,甚至 EF 都做不到,并且可以与 Linq 一起使用,因此运行基准测试是一个更好的选择。 【参考方案1】:

ORM(对象关系映射器)是一种在应用程序和数据源之间创建层并返回关系对象而不是返回的工具 (就您正在使用的 c# 而言)ADO.NET 对象。这是每个 ORM 都会做的基本事情。

为此,ORM 通常会执行查询并将返回的DataReader映射 到 POCO 类。 Dapper 仅限于此。

为了进一步扩展这一点,一些 ORM(也称为“完整 ORM”)会做更多的事情,例如为您生成查询以使您的应用程序数据库独立,缓存您的数据以供将来调用,为您管理工作单元等等.所有这些都是很好的工具,为 ORM 增加了价值;但它伴随着成本。实体框架属于此类。

要生成查询,EF 必须执行附加代码。缓存提高了性能,但管理缓存需要执行额外的代码。 EF 提供的工作单元和任何其他附加功能也是如此。所有这一切都为节省了编写额外代码的时间,而 EF 支付了成本。

成本就是性能。由于 Dapper 做的是非常基础的工作,所以它更快;但是您必须编写更多代码。由于 EF 做的远不止这些,它(有点)慢;但你必须编写更少的代码。

那么为什么您的测试显示相反的结果? 因为你正在执行的测试没有可比性。

如上所述,完整的 ORM 具有许多好的特性;其中之一是 UnitOfWork。跟踪是 UoW 的职责之一。当对象第一次被请求(SQL 查询)时,它会导致到数据库的往返。然后将该对象保存在内存缓存中。完整的 ORM 跟踪对此已加载对象所做的更改。如果再次请求相同的对象(包括已加载对象的同一 UoW 范围内的其他 SQL 查询),它们不会执行数据库往返。相反,它们从内存缓存中返回对象。这样可以节省大量时间。 Dapper 不支持此功能,这会导致它在您的测试中执行较慢。

但是,此优势仅适用于多次加载相同对象的情况。此外,如果加载到内存中的对象数量过多,则会降低整个 ORM 的速度,因为检查内存中的对象所需的时间会更长。同样,这种好处取决于用例。

【讨论】:

在编写复杂查询时,在某些情况下 EF 不会生成最佳 SQL,无论如何您都必须手动执行。所以我不会说 EF 真的很“完整”,它只是对非常简单的查询有帮助,但你必须彻底了解它才能有效地使用它,你也必须彻底了解 SQL,因此,你必须了解 2 大当你刚开始阅读一本关于 EF 的书时,它看起来非常简单和有希望,而不是预期的 1。但是日复一日,您一次又一次地面临新的挑战。 其中一些是通过棘手的 LINQ 解决的,而有些则仅使用纯 SQL 解决。您花费大量时间来了解您可以使用 EF 做什么以及不能做什么。项目的工作量越大,LINQ 查询就越显示出它们的低效率,你也必须用纯 SQL 重写它们。然后你意识到你必须关闭它的默认自动跟踪器并使用一些第三方库,比如 EntityFramework-Plus 来让它更快地工作。最后你认为发生了什么?为什么我选择了这个完整的 ORM 并花了很多时间来学习它,而现在我只将它用于简单的查询?!然后你会找到 Dapper。 @Sergey:同意;但也很少有其他方面需要考虑。请阅读this博客。 @Sergey: "And then you find Dapper." 不错的选择。恕我直言,在某些情况下,全 ORM、微 ORM 和手写查询发挥了它们的作用并具有它们的重要性。设计决定使用什么以及我们应该从中得到什么。 我已经阅读了这篇文章。我并没有轻蔑地谈论 ORM。相反,我认为人们付出了很大的努力来让它以最好的方式工作,而且它现在真的很有效。我真正的意思是你必须同时学习 SQL 和 ORM。 Martin F. 也说了同样的话,甚至更多——你必须先学习 SQL。我想说的是,对于刚开始通过 EF 使用 DB 的初学者,每本书和每篇文章都应该以大字体警告这一点。但事实并非如此,因此,新手会像我一样陷入误解和错误的期望中。【参考方案2】:

I read many articles which says that Dapper is faster than Entity Framework

互联网上大多数基准测试的问题在于他们将 EF Linq 与 Dapper 进行比较。这也是你所做的。这是不公平的。自动生成的查询 (EF) 通常不等于优秀开发人员编写的查询。

这个,

IEnumerable<Employee> emplist = hrctx.Employees.ToList();

应该换成这个。

IEnumerable<Employee> emplist = hrctx.Employees.FromSql(@"Select * From Employees").AsNoTracking();

编辑:

正如@mjwills 所指出的,下面是insertupdateselect 语句的结果表。

Dapper 的性能优于 EF Core 2。但是,可以看出,对于 EF 普通查询,差异非常小。我已经发布了complete details here。

【讨论】:

EF Linq to Dapper 是最准确的比较。您知道有多少开发人员在使用 EF 时会手工制作查询? Ef Linq to Dapper 是基于使用情况的苹果对苹果的比较。【参考方案3】:

Entity Framework Core 2.0 vs. Dapper performance benchmark, querying SQL Azure tables 的文章证实了 Dapper 有点快,但不足以忽略“完全 ORM”的好处。

【讨论】:

那篇文章做了很多错误的假设,与现实的测试用例相去甚远。查看this reddit thread 了解更多信息。 @Alternatex,感谢您的链接。但结论是一样的:Dapper 的性能只是稍微好一点,但 EF 的功能要多得多。【参考方案4】:

将它们混合在一起没有问题。在我当前的项目中,我使用 Dapper 来选择数据,使用 EF 来创建和更新以及数据库迁移。

当涉及到涉及两个以上表或存在一些复杂操作(由多个列连接、使用 >= 和

【讨论】:

最后一句话不适用于 EF-core 当前版本:2.1.1。另外,FWIW,我也不同意第二段的开头。在 LINQ 中编写复杂的查询比在 SQL 中容易得多,尤其是。使用导航属性时。最后,这并不能真正回答为什么 EF 在这种特定情况下更快的问题。 @GertArnold 我找不到在没有 DbSet ***.com/questions/45698359/… 的情况下映射原始 SQL 查询的方法。我你知道怎么做,请问你在哪里可以找到如何做到这一点?至于什么更容易使用,这是一个品味问题。以我的经验,原始 SQL 更灵活。对我来说。 不完全是FromSq,而是:docs.microsoft.com/en-us/ef/core/modeling/query-types

为啥选择实体框架? [关闭]

】为啥选择实体框架?[关闭]【英文标题】:WhyEntityFramework?[closed]为什么选择实体框架?[关闭]【发布时间】:2011-05-1816:32:22【问题描述】:我的问题是为什么我要使用实体框架而不是其他XYZ。任何人都可以对此给出一个清晰的... 查看详情

mysqldump导出来.sql文件导入数据库的速度为啥比自己写的insert语句快

参考技术A导出的sql文件有锁表,插入数据时不更新索引所以速度快。 参考技术B应该不会吧···mysqldump导出来的文件可以打开的,里面的数据就是用insert插入的啊是不是因为自己做数据的话需要做循环,而导入数据库时直接执行... 查看详情

为啥这个算法在 python 中的运行速度比在 C++ 中快得多?

】为啥这个算法在python中的运行速度比在C++中快得多?【英文标题】:WhydoesthisalgorithmworksomuchfasterinpythonthaninC++?为什么这个算法在python中的运行速度比在C++中快得多?【发布时间】:2016-02-0618:17:17【问题描述】:我正在阅读Robert... 查看详情

实体框架中的序列比身份更快吗?

】实体框架中的序列比身份更快吗?【英文标题】:IsSequencefasterthanIdentityinEntityFramework?【发布时间】:2016-05-1707:08:16【问题描述】:听说在SqlServer中Sequence比Identity快。但是,我认为在实体框架中使用它不是一个好主意。因为,... 查看详情

mysql数据库:为啥sql语句在查询分析中的执行速度远远快于在应用程序的(而且有时候后者慢的很多)

在程序中同一个sql语句第一次执行时间是0.001,第二次执行时间是0.1数量级的,而且sql语句本身执行所需时间至少在0.0001数量级,数据库在本地,难道只是数据库连接浪费了用掉了这些时间(刚看了下框架中源码,sql语句执行的... 查看详情

为啥选择 JMS 作为异步解决方案?为啥它比简单的实体 bean 更好?

】为啥选择JMS作为异步解决方案?为啥它比简单的实体bean更好?【英文标题】:WhychoosingJMSforasynchronoussolution?Whyisitbetterthanasimpleentitybean?为什么选择JMS作为异步解决方案?为什么它比简单的实体bean更好?【发布时间】:2011-01-0623... 查看详情

为啥这段代码的执行速度比预期的要快?

】为啥这段代码的执行速度比预期的要快?【英文标题】:Whyisthiscodeexecutingfasterthanexpected?为什么这段代码的执行速度比预期的要快?【发布时间】:2009-04-0314:49:20【问题描述】:我有这个代码:publicvoidreplay()longprevious=DateTime.Now... 查看详情

如果删除 AsNoTraking,速度会更快 - 为啥? - 实体框架 5.0 - SQL Server 2008 R2

】如果删除AsNoTraking,速度会更快-为啥?-实体框架5.0-SQLServer2008R2【英文标题】:BetterSpeedifremovingAsNoTraking-why?-EntityFramework5.0-SQLServer2008R2如果删除AsNoTraking,速度会更快-为什么?-实体框架5.0-SQLServer2008R2【发布时间】:2013-07-1507:4... 查看详情

在我的情况下,为啥 rds 的执行速度比 redshift 快?

】在我的情况下,为啥rds的执行速度比redshift快?【英文标题】:Whyisrdsperformingfasterthanredshiftinmycase?在我的情况下,为什么rds的执行速度比redshift快?【发布时间】:2018-11-0210:46:25【问题描述】:我有一个RDS实例:db.t2.xlarge(4个v... 查看详情

为啥sql数据库的表用vba导到excel中的速度比excel的数据导入功能慢

我的代码很简单,就是打开数据库执行某表的复制。一级小白的方法可行,但是不能用到其它人的不同名字的数据库的同一个表格复制,而我现在可以,就是很慢。而且小白一级说的我也不知道怎样编写代码。在使用excel的时候... 查看详情

为啥实体框架没有映射我订单中的客户实体?

】为啥实体框架没有映射我订单中的客户实体?【英文标题】:Whydoestheentityframeworknotmapthecustomerentityinmyorder?为什么实体框架没有映射我订单中的客户实体?【发布时间】:2021-08-2722:02:06【问题描述】:我有一个订单实体,其中... 查看详情

存储过程和实体框架的性能

】存储过程和实体框架的性能【英文标题】:Performanceofstoredprocedures&EntityFramework【发布时间】:2012-04-1812:00:22【问题描述】:通过我的实体模型调用存储过程会导致比直接调用慢得多的性能有什么明显的原因吗?首先,我不... 查看详情

为啥在 GPU 中执行方法的时间比在混合器项目中的 CPU 中执行的时间更多?

】为啥在GPU中执行方法的时间比在混合器项目中的CPU中执行的时间更多?【英文标题】:WhythetimetoexecuteamethodinGPUismorecomparetoinCPUinhybridizerprojects?为什么在GPU中执行方法的时间比在混合器项目中的CPU中执行的时间更多?【发布时间... 查看详情

大量数据多表联合查询时时,使用视图,是否比直接查询速度要快!有高手请给讲讲,如何提高查询速度

1、简化应用程序。视图做为数据库中的一种实体,实际上存在的只是它的脚本,而它的内容并不真正的单独存在一份。一般,可以对复杂的应用程序从功能角度进行分析,将可以与其它的应用程序共用的那一部分,分离出来。... 查看详情

获取实体框架 6 在其下面的 SELECT 语句中使用 NOLOCK

】获取实体框架6在其下面的SELECT语句中使用NOLOCK【英文标题】:GetEntityFramework6useNOLOCKinitsunderneathSELECTstatements【发布时间】:2014-09-0107:44:29【问题描述】:我在MVC5项目中使用实体框架6。如您所知,如果我们在其中使用WITH(NOLOCK)... 查看详情

实体框架中的一个事务中的许多更新语句

】实体框架中的一个事务中的许多更新语句【英文标题】:ManyupdatestatementsinoneTransactioninEntityFramework【发布时间】:2012-07-0207:19:18【问题描述】:我需要更新多个更新语句,但所有更新语句都应该适用于自动性,即更新全部或不... 查看详情

为啥我的 Spark 运行速度比纯 Python 慢?性能比较

】为啥我的Spark运行速度比纯Python慢?性能比较【英文标题】:WhydoesmySparkrunslowerthanpurePython?Performancecomparison为什么我的Spark运行速度比纯Python慢?性能比较【发布时间】:2016-01-0604:00:34【问题描述】:在这里激发新手。我尝试使... 查看详情

使用实体框架执行存储过程[重复]

】使用实体框架执行存储过程[重复]【英文标题】:Executestoredprocedureusingentityframework[duplicate]【发布时间】:2016-12-2800:39:25【问题描述】:是否可以使用EF执行存储过程,使用内连接和左外连接从两个或多个表中选择数据库中的记... 查看详情