阿里云「飞天发布时刻」2024来啦!新产品、新特性、新能力、新方案,等你来探~ 了解详情
写点什么

挖掘 ADO.NET Entity 框架的性能

  • 2008-02-23
  • 本文字数:2358 字

    阅读完需:约 8 分钟

ADO.NET 团队最近讨论了 ADO.NET Entity 框架的各种性能特征。ADO.NET Entity 框架在 12 月已经进入它的第三个 beta 版本,自那时起开发团队就开始为开发人员提供了使用该框架的相关信息。而现在,则为开发人员提供了框架性能方面的信息。

本文鞭辟入里地介绍了 ADO.NET Entity 框架的性能,演示了如何提高简单查询速度的方法,并阐释了框架的性能特征。

需要重点指出的是,当一个抽象层或者类似 EDM(译注:指 Entity Data Model)的模块被用来转换数据库的关系样式时,会带来一定的性能损失。

查询与结果

本文使用了 NorthWind 数据库作为模型,并创建了一个简单查询:

(NorthwindEntities ne =  NorthwindEntities()) <br></br>{ <br></br> (Order o  ne.Orders) <br></br>    { <br></br> i = o.OrderID; <br></br>    } <br></br>}

测试时,我们的每个查询对整个 848 行数据进行了 10 次遍历。结果很有意思,第 1 次运行时耗费了 4241 毫秒,而接下来的每次运行则平均耗费 13 毫秒左右的时间。最耗时的一部分内容是 ObjectContext 的创建,而在执行任意一个访问数据库的操作时,都会有一些耗时的操作发生。

每次操作的百分比值可以给我们一些启示:

  • 装载元数据(11%)
  • 初始化元数据(14%)
  • 打开连接(8%)
  • 生成视图(56%)
  • 装载程序集(2%)
  • 跟踪(1%)
  • 实例化(7%)
  • 其它(1%)

耗时百分比值最大的是视图生成,它达到了惊人的 56%。既然视图生成是造成性能损耗的罪魁祸首,那么开发人员最好是使用命令行工具 EDM 生成器(EdmGen.exe),运行时需要加上视图生成命令参数(/mode:ViewGeneration),它的输出内容为一个代码文件(C#或者 VB.NET),可以包含在项目中。视图的预生成可以将启动时间降低到 2933 毫秒,而对于循环遍历操作,整个时间可以降低 28%。生成视图并随着应用程序一起发布是提高性能的妙方,但其缺点则在于视图不再是动态的,一旦模型发生改变,就需要重新生成以保持同步。

查询性能

需要指出的是关于性能的主要设计要素是查询缓存。一旦执行了查询,它的一部分内容就被维持在全局缓存中。由于查询与元数据缓存的存在,使得第二次运行的执行速度总是比第一次运行快。例如,如下的 Entity SQL 查询:

(PerformanceArticleContext ne = PerformanceArticleContext()) <br></br>{ <br></br> ObjectQuery<Orders> orders = ne.CreateQuery<Orders>(); <br></br> (Orders o orders) <br></br> { <br></br> i = o.OrderID; <br></br> } <br></br>}

第一次运行该查询耗时 179 毫秒,但下一次运行则只耗费了 15 毫秒的时间。首次运行与后续运行在执行方面的区别在于它构建了能够为执行传递 provider 的命令树(command tree)。

LINQ 查询在执行方式上与 Entity SQL 查询相似。例如,下面的查询:

(PerformanceArticleContext ne = PerformanceArticleContext()) <br></br>{ <br></br> var orders = from order ne.Orders <br></br> select order; <br></br> (Orders o orders) <br></br> { <br></br> i = o.OrderID; <br></br> } <br></br>}

首次执行 LINQ 查询耗时 202 毫秒,而随后的执行耗时 18 毫秒,两者的差距还要低于 Entity SQL。可以看到,使用编译了的 LINQ 查询对于性能的提高更为明显。编译 LINQ 查询的好处在于它构建了表达树(expression tree),当查询被编译时,后续的执行就不需要重建表达树了。编译的 LINQ 查询代码看起来像这样:

Func<PerformanceArticleContext, IQueryable<Orders>> compiledQuery = CompiledQuery.Compile((PerformanceArticleContext ne) => (from o ne.Orders select o)); <br></br>(PerformanceArticleContext ne = PerformanceArticleContext()) <br></br>{ <br></br> (Orders o compiledQuery(ne)) <br></br> { <br></br> i = o.OrderID; <br></br> } <br></br>}

注意,PerformanceArticleContext 是一个委托。对于编译了的 LINQ 查询而言,第一次执行耗时 305 毫秒,而随后的执行时间则为 15 毫秒。结果并不惊人,值得关注的是编译的 LINQ 查询比之常规方式的 LINQ 查询,执行时间少了 3 毫秒。或许对于几个查询而言,这算不上什么,但如果有数以千计的查询,这样的性能提升就倍显价值所在了。

ADO.NET 团队建议开发人员在查询中应谨慎使用 Track/NoTrack 选项:

在之前的例子中,所有放在对象创建中的查询结果都被添加到 ObjectStateManager 中,因此我们能够跟踪它们的更新。如果没有必要跟踪对象的更新和删除,那么最好是使用 NoTracking 合并项。例如,在一个 ASP.NET Web 应用程序中,如果它要查询一个指定的分类名称,但却不需要对返回的数据进行更新,那么 NoTracking 就会是一个不错的选择。在这种情形下,使用 NoTracking 的查询会在性能方面得到改善。

基于前面的一组数字,NoTracking 选项能够大幅度地降低执行的时间,而其中性能的提升主要源自于我们停止了对变更的跟踪以及对关系的管理。如果使用 NoTracking 查询,无论是第一次执行还是随后的执行,编译的 LINQ 查询都要优于标准的 LINQ 查询。注意,编译的 LINQ 查询的第二次执行与 Entity SQL 查询的第二次执行相等。

ADO.NET 团队同时还提醒开发者在创建查询时,有一些内容必须铭记于心:

在 Entity 框架中优化查询性能时,应该针对特定的编程场景做出最佳选择。这里列举了几个关键项:

  • ObjectContext 的首次创建包含了装载和验证元数据的性能损耗。
  • 任何一个查询的首次执行都包含了构建一个查询缓存的性能损耗,以利于提高后续查询的执行速度。
  • 编译的 LINQ 查询比未编译的 LINQ 查询要快。
  • 如果不需要跟踪数据的变更与数据的关系,或者对大数据对象进行流操作,那么通过 NoTracking 合并项执行查询,效果会更佳。

若要了解更多关于 ADO.NET 和 Entity 框架的信息,敬请访问 ADO.NET 的团队博客

查看英文原文: Digging into the Performance of the ADO.NET Entity Framework

2008-02-23 08:143013
用户头像

发布了 79 篇内容, 共 17.6 次阅读, 收获喜欢 1 次。

关注

评论

发布
暂无评论
发现更多内容

MySQL表设计实践

天高任鸟飞

MySQL

Spring高手之路14——深入浅出:SPI机制在JDK与Spring Boot中的应用

砖业洋__

spring jdk springboot spi spring-boot

程序员如何提高写代码效率?

树上有只程序猿

程序员 工具

直播拍卖APP开发现成源码,PHP技术栈结构

软件开发-梦幻运营部

经过实践的能够提效 2000% 的低代码(前端中后台)工具设计介绍

Geek_bb8221

前端 后端 低代码前端

自然语言处理:机器理解人类语言的奇迹

测吧(北京)科技有限公司

测试

2024中国(深圳)国际锂电及储能材料展览会

吹吹晚风

AI时代,企业如何做好数智化合同管理?

用友BIP

数智合同

ARTS 打卡 第四周,游刃有余

三掌柜

ARTS 打卡计划

Pandas数据清理

3D建模设计

数据分析 pandas

自动驾驶点云标注的挑战与解决方案

来自四九城儿

数据科学中的数据库简介

3D建模设计

数据科学

移动端IM即时通讯系统开发,私有化部署IM聊天源码核心功能概括

山东布谷科技胡月

IM 即时通讯IM 语音交友源码 软件源码 IM聊天系统

如何入门人工智能?

测吧(北京)科技有限公司

测试

智能机器人:将AI带入我们的日常生活

测吧(北京)科技有限公司

测试

每一座屎山代码背后,都藏着一堆熟读代码规范的研发

CODING DevOps

Maxon 802.11ax QCN9074 & QCN9024 WiFi6 modules

wifi6module

数据可视化:理论与技术

3D建模设计

数据可视化

SRM询价采购系统(源码),提升企业采购效率的关键

金陵老街

Java Vue springboot

财税一体,高效合规,用数据引领中企出海价值创造

用友BIP

中企出海

2023年最全1228道Java中高级面试题附答案详解,最全面详细,看完稳了

架构师之道

编程 java面试

IPQ9574 with QCN9274 Solution for Industrial Applications|WiFi 7

wallyslilly

自动驾驶点云标注技术的现状与未来发展

来自四九城儿

提升数学效率:导航 Numpy 数组操作

3D建模设计

Python 数据工程

低代码让开发变得不再复杂

这我可不懂

低代码 应用开发

人工智能 | 深度学习—模仿人脑的未来

测吧(北京)科技有限公司

测试

计算机视觉:让机器看懂世界

测吧(北京)科技有限公司

测试

2024广州国际精密注塑技术装备展览会

吹吹晚风

QCN9074 and QCA9892 chips-Detailed explanation of the different wireless standards

wifi6-yiyi

wifi6 WiFi 7

利用 Python 中的地理空间数据与 GeoPandas

3D建模设计

Python 地理空间数据

内外统一的边缘原生云基础设施架构——火山引擎边缘云

火山引擎边缘云

云原生 边缘计算 边缘云

挖掘ADO.NET Entity框架的性能_.NET_Robert Bazinet_InfoQ精选文章