Linq to Sql的执行可能无法复用查询计划
Sql Server 在执行一条查询语句之前都对对它进行“编译”并生成“查询计划”,查询计划告诉Sql Server的查询引擎应该用什么方式进行工作。Sql Server会根据当前它可以收集到的各种信息(例如内存大小,索引的统计等等)把一条查询语句编译成它认为“最优”的
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; |
请注意上图中被选中的两条记录,它表明了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方法又不能影响我们的优化操作……
因此,我想在这里说的是:这个问题我们没法进行优化。
不过我们还是幸运的,因为我根据我的经验,似乎在查询条件中使用长度不等的字符串作为参数的情况并不多见。不是么?
点击查看原文>>

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

HQL和SQL在Hibernate框架中進行比較:HQL(1.物件導向語法,2.資料庫無關的查詢,3.類型安全),而SQL直接操作資料庫(1.與資料庫無關的標準,2.可執行複雜查詢和資料操作)。

《OracleSQL中除法運算的用法》在OracleSQL中,除法運算是常見的數學運算之一。在資料查詢和處理過程中,除法運算可以幫助我們計算欄位之間的比例或得出特定數值的邏輯關係。本文將介紹OracleSQL中除法運算的用法,並提供具體的程式碼範例。一、OracleSQL中除法運算的兩種方式在OracleSQL中,除法運算可以用兩種不同的方式來進行

Oracle和DB2是兩個常用的關聯式資料庫管理系統,它們都有自己獨特的SQL語法和特性。本文將針對Oracle和DB2的SQL語法進行比較與區別,並提供具體的程式碼範例。資料庫連接在Oracle中,使用以下語句連接資料庫:CONNECTusername/password@database而在DB2中,連接資料庫的語句如下:CONNECTTOdataba

12306訂票app下載最新版是一款大家非常滿意的出行購票軟體,想去哪裡就去那裡非常方便,軟體內提供的票源非常多,只需要通過實名認證就能在線購票,所有用戶的出行車票機票都可以輕鬆買到,享受不同的優惠折扣。還能提前開啟預約搶票,預約飯店、專車接送都是可以的,有了它想去哪裡就去那裡一鍵購票,出行更加簡單方便,讓大家的出行體驗更舒服,現在小編在線詳細為12306用戶帶來查看歷史購票記錄的方法。 1.打開鐵路12306,點擊右下角我的,點擊我的訂單 2.在訂單頁面點擊已支付。 3.在已支付頁

學信網如何查詢自己的學歷?在學信網中是可以查詢到自己的學歷,很多用戶都不知道如何在學信網中查詢到自己的學歷,接下來就是小編為用戶帶來的學信網查詢自己學歷方法圖文教程,感興趣的用戶快來一起看看吧!學信網使用教程學信網如何查詢自己的學歷一、學信網入口:https://www.chsi.com.cn/二、網站查詢:第一步:點選上方學信網位址,進入首頁點選【學歷查詢】;第二步:在最新的網頁中點選如下圖箭頭所示的【查詢】;第三步:之後在新頁面點選【的登陸學信檔案】;第四步:在登陸頁面輸入資料點選【登陸】;

資料庫技術大比拼:Oracle和SQL的差別有哪些?在資料庫領域中,Oracle和SQLServer是兩種備受推崇的關聯式資料庫管理系統。儘管它們都屬於關係型資料庫的範疇,但兩者之間存在著許多不同之處。在本文中,我們將深入探討Oracle和SQLServer之間的區別,以及它們在實際應用中的特徵和優勢。首先,Oracle和SQLServer在語法方面存

MySQL與PL/SQL是兩種不同的資料庫管理系統,分別代表了關係型資料庫和過程化語言的特性。本文將比較MySQL和PL/SQL的異同點,並附帶具體的程式碼範例進行說明。 MySQL是一種流行的關聯式資料庫管理系統,採用結構化查詢語言(SQL)來管理和操作資料庫。而PL/SQL是Oracle資料庫特有的過程化語言,用於編寫預存程序、觸發器和函數等資料庫物件。相同

中關村消息:4月18日早上,華為突然宣布P70系列手機開啟先鋒計畫正式開售,想要購買的朋友要準備行動起來了,按照以往慣例,華為的旗艦手機非常搶手,會一直處於缺貨狀態。這次華為P70系列改名為Pura,意為純粹。在此前華為餘承東表示:自2012年起,華為P系列智慧型手機便如同忠實的伙伴,伴隨全球億萬用戶度過了無數珍貴時刻,共同見證了生活中的美好與精彩紛呈。他深刻感悟,每位選擇華為P系列的用戶所給予的信任與熱愛,無異於一股強大的推動力,始終鼓舞著華為在創新之路上堅定前行。 Pura的意思是純粹的。
