频 道 直 达 - 新闻 - 读书 - 培训 - 教程 - 前沿 - 组网 - 系统应用 - 安全 - 编程 - 存储 - 操作系统 - 数据库 - 服务器 - 专题 - 产品 - 案例库 - 技术圈 - 博客 - BBS
51CTO.COM_中国领先的IT技术网站
找资料:

挖掘ADO.NET Entity框架的性能

作者: Robert Bazinet 出处:InfoQ中文站 2008-02-24 12:19    砖    好    评论   进入论坛
阅读提示:本文鞭辟入里地介绍了ADO.NET Entity框架的性能,演示了如何提高简单查询速度的方法,并阐释了框架的性能特征。当一个抽象层或者类似EDM(译注:指Entity Data Model)的模块被用来转换数据库的关系样式时,会带来一定的性能损失。

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

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

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

查询与结果

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

(NorthwindEntities ne =  NorthwindEntities()) 
{
(Order o  ne.Orders)
{
i = o.OrderID;
}
}

测试时,我们的每个查询对整个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()) 
{
ObjectQuery orders = ne.CreateQuery();
(Orders o orders)
{
i = o.OrderID;
}
}

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

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

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

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

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

注意,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合并项执行查询,效果会更佳。

【相关文章】

【责任编辑:碧海蓝天 TEL:(010)68476606】

专题
主流防火墙性能对比分析
开源框架Eclipse发展历程
ASP.NET 2.0基础开发指南
.NET移动与嵌入式技术专题
.NET Framework新手入门专题
我也说两句

匿名发表

(如果看不清请点击图片进行更换)


中 国 领 先 的 IT 技 术 网 站 ·
技 术 成 就 梦 想
·Java基础教程 (查看67105次)
·UML类图详解 (查看61927次)
·UML统一建模语言 (查看33748次)
·C#技术开发指南 (查看32118次)
·Java编程开发手册 (查看30455次)
·Java编程开发手册 (1195个砖)
·Java基础教程 (429个砖)
·C#技术开发指南 (308个砖)
·.NET开发手册 (236个砖)
·PB开发教程 (223个砖)
·Java编程开发手册 (654个好)
·Java基础教程 (574个好)
·.NET开发手册 (271个好)
·PB开发教程 (212个好)
·Delphi开发技术手册 (186个好)
订阅技术快讯
电子杂志下载
名称:2007路由技术大全
简介:《2007路由技术大全》由51CTO.com网站特别策划制作,该书包括路由器技术、路由器产品、路由器配置、安全设置、路由器故障处理、路由器密码恢复,以及广大网友在实践使用中的心得经验和技巧文章,内容注重实用性,适用于初学者入门,也适合多年从业者提高,是一本实践和理论完
名称:网络安全精品应用黄皮书
简介:《2007精品网络安全黄皮书》包括了9个大类24个小类, 800余篇文章,内容包含了熊猫烧香病毒、DDOS攻击、ARP病等热点问题的介绍及解决方案。从病毒查杀、防范、系统、数据等各方面的安全设置到黑客技术的了解、防范,涉及到了安全应用的全部领域, 由浅至深内容全面。
名称:Vista精品应用黄皮书
简介:《Vista精品应用黄皮书》囊括了Vista的各方面内容。此次的精简版,是将里面的内容做了提取,便于用户下载和使用。内容包含了各种Vista的安装与实施、技巧与解析以及各种Vista相关学习文档和相关软件的安全下载。该电子书是了解和应用Vista人员必备的工具手册,并且也是第一本