是否会成为问题——Linq to Sql的执行可能无法复用查询计划

查询计划

Sql Server在执行一条查询语句之前都对对它进行“编译”并生成“查询计划”,查询计划告诉Sql Server的查询引擎应该用什么方式进行工作。Sql Server会根据当前它可以收集到的各种信息(例如内存大小,索引的统计等等)把一条查询语句编译成它认为“最优”的查询计划。很显然,得到这样一个查询计划需要消耗CPU资源,而大部分的查询语句每次经过编译所得到的查询计划往往是相同的,因此除非指定了RECOMPILE选项,Sql Server在执行查询语句时,会对查询计划进行缓存——也就是说,如果是相同的查询语句,Sql Server只会对它进行一次编译操作,然后在每次执行时对查询计划进行复用。查询计划如果无法复用,则会在相当程度上降低数据库性能——因为过多的CPU被消耗在查询语句的编译上。各种提及数据库查询优化的资料上大都会提到这一点,我们往往通过查看性能计数器的某些统计,或者Sql Server系统表中的一些记录,就可以判定您的数据库应用是否出现了这个问题。

对于存储过程来说,复用查询计划是轻而易举的。不过对于那些喜欢在程序代码中拼接Sql字符串的朋友来说,日子就有些不好过了。Sql Server是根据您传入的Sql语句来缓存查询计划的,如果您“强行”拼接了Sql字符串并交给Sql Server执行,那么查询计划被复用的可能性微乎其微。因此,我们绝对应该杜绝拼接字符串的行为,因为这不仅仅造成了传统的Sql注入!而那些习惯相对较好的朋友,则会使用带参数的Sql语句,在交给Sql Server执行时就可能复用查询计划。因为和调用存储过程相比,发送带参数的Sql语句只是将使用了sp_executesql命令而已,每次执行的查询语句还是相同的。

问题何在?

对于复用查询计划的问题,在上文中我说了这么一句话:“……使用带参数的Sql语句,在交给Sql Server执行时就可能复用查询计划……”。我为什么要说“可能”?因为即时使用带参数的Sql语句,在某些情况下我们还是无法对查询计划进行复用。这是怎么一回事儿呢?我们还是直接从Linq to Sql来产生Sql语句,然后观察Sql Server的行为吧。

请看以下的代码(示例所操作的数据表与《在Linq to Sql中管理并发更新时的冲突(2):引发更新冲突》一文相同):

LinqToSqlDemoDataContext dataContext = new LinqToSqlDemoDataContext();
dataContext.Log = Console.Out;

Video video1 = dataContext.Videos.SingleOrDefault(
    v => v.Introduction == "Hello");
Video video2 = dataContext.Videos.SingleOrDefault(
    v => v.Introduction == "Hello World");

Console.ReadLine();

还是查看输出:

SELECT [t0].[VideoID], [t0].[Introduction], [t0].[SiteID]
FROM [dbo].[Video] AS [t0]
WHERE [t0].[Introduction] = @p0
-- @p0: Input NVarChar (Size = 5; Prec = 0; Scale = 0) [Hello]
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.21004.1

SELECT [t0].[VideoID], [t0].[Introduction], [t0].[SiteID]
FROM [dbo].[Video] AS [t0]
WHERE [t0].[Introduction] = @p0
-- @p0: Input NVarChar (Size = 11; Prec = 0; Scale = 0) [Hello World]
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.21004.1 

两局Sql语句完全相同,按我们刚才的说法,Sql Server应该缓存了查询计划。但是我们通过查看sys.syscacheobjects的相关数据可以看出,事情并非如同我们想象的那样:

SELECT cacheobjtype, sql FROM sys.syscacheobjects;
DBCC freeproccache;

linq2sql-cannot-cache-compiled-plan-1.jpg

请注意上图中被选中的两条记录,它表明了Sql Server并没有缓存执行计划。

为什么?这两次执行究竟有什么区别?通过Linq to Sql很容易看出,两次执行所用到的参数不同。更进一步,如果对比Linq to Sql输出的缓存以及sys.syscacheobjects视图中的记录,就会发现:其实仅仅是参数的尺寸不同。

没错,就是这个原因。在使用ADO.NET时,如果SqlParameter的Type是nvarchar,并且没有指定Size属性,则可能就会因为具体参数的尺寸不同而造成查询计划无法复用的结果。这一点,很多人都忽视了。

优化方案

在使用ADO.NET进行开发时,该问题其实很容易解决。我们只要指定SqlParameter的Size属性即可。由于每次指定了一个固定的参数尺寸,Sql Server就能够复用查询计划了。

不过我们现在在使用Linq to Sql,又该怎么做呢?嗯,我们可以为XXXXDataContext重写(override)SubmitChanges方法,在其中获得需要执行的SqlCommand对象(具体方法请参考《在Linq to Sql中管理并发更新时的冲突(1):预备知识》一文),获得其中的SqlParameter参数,并设定它们的Size属性。我们可以使用Custom Attribute来标注应该为哪个属性设置什么样的Size,如果再结合AOP,哈哈……

等等,先别想那么远。即使得到了SqlCommand对象,它所生成的Sql语句是以@p0、@p1作为参数名,您知道该修改哪个SqlParameter对象吗?再者,SubmitChanges方法只是提交我们做出的修改,但是在一般的系统中,查询操作的次数和性能消耗大大超过修改操作,而重写了SubmitChangeds方法又不能影响我们的优化操作……

因此,我想在这里说的是:这个问题我们没法进行优化。

不过我们还是幸运的,因为我根据我的经验,似乎在查询条件中使用长度不等的字符串作为参数的情况并不多见。不是么?

转载于:https://www.cnblogs.com/JeffreyZhao/archive/2007/11/21/linq-to-sql-cannot-cache-compiled-plan.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/381691.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

介绍及安装

不知读者是否听说过“宠物大战”?大意为Sun公司为帮助开发人员和架构师使用J2EE技术,发布了一个在线宠物商店Sun Java Pet Store。而微软公司则利用.NET技术也发布了一个实现同样功能的PetShop,并且在代码数量、性能等各方面对二者进行了比较…

自定函数获取datagrid,datalist,rpeater控件中header,footer栏中控件

在论坛上看到很多关于datagrid,gridview,datalist,rpeater提取header,footer中控件的问题,整理了一下.供大家分享下面我以DataGrid为便进行说明.footer栏又称页脚栏,在很多时候我们可以在该栏放页码及相当的功能键.但是最后在获得这些控件引用的时候就会有点麻烦,由于footer(页…

随机广告图片

1<script language”JavaScript”>2var imageList newArray;3imageList[0] “image1.jpg”;4imageList[1] “image2.jpg”;5imageList[2] “image3.jpg”;6imageList[3] “image4.jpg”;7var urlList newArray;8urlList[0] “http://some.host/”;9urlList[1] “http://a…

Core IO学习心得

最近看Core IO的内容&#xff0c;有一些心得给大家共享一下&#xff1a; Core IO作为微软IT基础架构优化框架中的一个部分。该框架包含三个部分&#xff1a;CIO&#xff0c;BPIO和APIO&#xff1a; CIO&#xff08;核心基础架构优化&#xff09;专注于核心基础机构组件&#x…

经典算法研究系列:十、从头到尾彻底理解傅里叶变换算法、上

经典算法研究系列&#xff1a;十、从头到尾彻底理解傅里叶变换算法、上 作者&#xff1a;July、dznlong 二零一一年二月二十日 推荐阅读&#xff1a;The Scientist and Engineers Guide to Digital Signal Processing&#xff0c;By Steven W. Smith, Ph.D。此书地址&#xf…

经典算法研究系列:十、从头到尾彻底理解傅里叶变换算法、下

经典算法研究系列&#xff1a;十、从头到尾彻底理解傅里叶变换算法、下 作者&#xff1a;July、dznlong 二零一一年二月二十二日 推荐阅读&#xff1a;The Scientist and Engineers Guide to Digital Signal Processing&#xff0c;By Steven W. Smith, Ph.D。此书地址&#…

调出sharepoint错误的详细页面

记录一个小技巧&#xff1a; 在开发sharepoint的时候经常出现" An unexpected error has occurred."的页面&#xff0c;让人非常的郁闷。 打开web.config, 找到&#xff1a; <SafeMode MaxControls"200" CallStack"false" DirectFileDepende…

职业生涯中12个最致命的想法

1、总觉得自己不够好  这种人虽然聪明、有历练&#xff0c;但是一旦被提拔&#xff0c;反而毫无自信&#xff0c;觉得自己不胜任。4、无条件地回避冲突  这种人一般会不惜一切代价&#xff0c;避免冲突。一位本来应当为部属据理力争的主管&#xff0c;为了回避冲突&#xf…

树链剖分入门讲解

“在一棵树上进行路径的修改、求极值、求和”乍一看只要线段树就能轻松解决&#xff0c;实际上&#xff0c;仅凭线段树是不能搞定它的。我们需要用到一种貌似高级的复杂算法——树链剖分。 树链&#xff0c;就是树上的路径。剖分&#xff0c;就是把路径分类为重链和轻链。 记…

选择模块数据读取

1if(Bname"")2{ 3 Response.Write("<script languagejavascript>alert(错误的链接地址&#xff01;);history.go(-1);</script>"); 4 Response.End(); 5 }6if(Bid106&&Sid!0)7{ 8 //<!-- 标准法规--> 9 if(Sid127…

Terrafugia希望在今年夏天带来真正可飞的Airplane

Terrafugia希望在今年夏天带来真正可飞的Airplane 大家都知道&#xff0c;Terrafugia的汽车飞机混合机种&#xff0c;他是是辆双座的汽车&#xff0c;拥有100-500英里的速度范围&#xff0c;一个独立的无铅汽油储备箱&#xff0c;同时配置有电子计算机&#xff0c;用来在空中飞…

四川汶川地震祈福赈灾宣传画、报纸头版精选第二版(超多图)

本篇Key词&#xff1a; 汶川地震祈福图片汶川地震祈福壁纸四川汶川地震祈福赈灾宣传画 四川汶川地震祈福赈灾宣传画 天使 不要害怕&#xff0c;手牵手渡过难关 孩子不哭 生命奇迹 从废墟中站起来 祝福灾区人民 众志成城&#xff0c;抗震救灾 众志成城&#xff0c;抗震救灾2 众…

2016年湖南省第十二届大学生计算机程序设计竞赛

题目&#xff1a; 任意门 听说这套题目是叉姐出的&#xff0c;感觉呵呵了。。。 据说现场牌都不够发的&#xff01;&#xff01;&#xff01;只能说给湖南省出的题目太强了&#xff0c;不适合新手去做&#xff0c;当然我这种老手也不见得做的多好&#xff0c;出了3题&#xf…

控件中的Events个人理解。

首先&#xff0c;了解一下与事件和委托有关的几个类和属性&#xff1a;Delegate, MulticastDelegate, EventHandler, EventHandlerList, EventHandlerList.ListEntry, Control, ComponentControl的Events属性是由System.ComponentModel.Component 继承而来,它是EventHandlerLis…

ManualResetEvent用法

ManualResetEvent 允许线程通过发信号互相通信。通常&#xff0c;此通信涉及一个线程在其他线程进行之前必须完成的任务。 public static ManualResetEvent mre new ManualResetEvent(false); ManualResetEvent建立时是把false作为start的初始状态&#xff0c;这个类用于通知另…

JavaScript: Cookie 详解、实例与应用

Cookie&#xff08;也&#xff09;是JavaScript中的一种机制&#xff0c;可以实现严格的跨页面全局变量的要求。 Cookie是存于用户硬盘的一个文件&#xff0c;这个文件通常对应于一个域名&#xff0c;当浏览器再次访问这个域名时&#xff0c;便使这个cookie可用。因此&#xff…

苹果电脑可以装windows系统吗_不只是桌面,这个 Windows 皮肤可以帮你全局美化 Windows 系统

追求个性化是个永恒不变的需求&#xff0c;而在主题这件事情上&#xff0c;和 Windows XP 那个百花齐放的时代相比&#xff0c;我们在 Windows 10 下能够享受到的官方主题大多都只是换换壁纸、改改配色这么简单。而在千篇一律的官方主题之外&#xff0c;美化社区的 Windows 10 …

SQL Server 2005: 存储过程签名

SQLSERVER 2005提供的对存储过程签名(signature)功能是我最喜欢的。如果我们要编写一个存储过程,执行该存储过程里的代码需要权限P,并且我们想要用户Alice可以执行这个存储过程&#xff0c;但是我们不想将权限P直接赋予给用户Alice&#xff0c; 我们可以用证书(certificate)对这…

手机能上wifi电脑不行_锦囊在此(电脑手机如何配置使用WIFI)

1.路由器接入电源(以下是以TP-LINK为例&#xff0c;其他路由器大同小异&#xff0c;重要是在于关闭DHCP服务器选项)2.打开电脑WIFI连接路由器(找对路由器名称&#xff0c;见路由器底标)(建议不要接入网线&#xff0c;配置好再接入网线)3.打开浏览器输入路由器后台网址(见路由器…

8位可控加减法电路设计_100以内数的认知也加减法详解

一、100 以内数的认识1、10个十是100,读作一百。100 是由10个十或100个一组成,它是一个三位数。2、数数时,可以一个一个的数,也可以二个二个的数,五个五个的数,十个十个的数。3、从右边起,第一位是个位,第二位是十位,第三位是百位。4、读数和写数,都从高位起。当计数器上个位或…