国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 數(shù)據(jù)庫 > SQL Server > 正文

SQL Server 2005 中的批編譯、重新編譯和計(jì)劃緩存問題(2)

2024-08-31 00:50:13
字體:
供稿:網(wǎng)友

  查詢計(jì)劃緩存及各種 set 選項(xiàng)(與 showplan 相關(guān)及其他)

  各種 set 選項(xiàng)——多數(shù)與 showplan 相關(guān)——以多種復(fù)雜的方式影響著查詢計(jì)劃和執(zhí)行上下文的編譯、緩存和重用。下表匯總了相關(guān)的詳細(xì)信息。

  應(yīng)按如下順序閱讀該表中的內(nèi)容。批處理通過表中第一列所指定的特定模式提交給 sql server。已提交的批處理的計(jì)劃緩存中可能存在、也可能不存在已緩存的查詢計(jì)劃。第 2 列和第 3 列描述了存在已緩存的查詢計(jì)劃時(shí)的情況;第 4 列和第 5 列說明了不存在已緩存的查詢計(jì)劃時(shí)的情況。在每個(gè)類別中,查詢計(jì)劃和執(zhí)行上下文的各種情況都是獨(dú)立的。表中說明了結(jié)構(gòu)(查詢計(jì)劃或執(zhí)行上下文)所發(fā)生的情況:是否被緩存、重用和使用。

模式名稱存在已緩存的查詢計(jì)劃時(shí)存在已緩存的查詢計(jì)劃時(shí)不存在已緩存的查詢計(jì)劃時(shí)不存在已緩存的查詢計(jì)劃時(shí)

  查詢計(jì)劃

  執(zhí)行上下文

  查詢計(jì)劃

  執(zhí)行上下文

  showplan_text, showplan_all, showplan_xml

  被重用(無編譯)

  被重用

  被緩存(編譯)

  生成一個(gè)執(zhí)行上下文,對(duì)其進(jìn)行緩存但不使用它

  statistics profile, statistics xml, statistics io, statistics time

  被重用(無編譯)

  不被重用生成并使用一個(gè)全新的執(zhí)行上下文,但不對(duì)其進(jìn)行緩存

  被緩存(編譯)

  生成并使用一個(gè)全新的執(zhí)行上下文,但不對(duì)其進(jìn)行緩存

  noexec

  被重用(無編譯)

  被重用

  被緩存(編譯)

  不生成執(zhí)行上下文(由于“noexec”模式)。

  parseonly(例如,在查詢分析器或 management studio 中按“分析”按鈕)

  無

  無

  無

  無

查詢計(jì)劃和執(zhí)行上下文的相關(guān)成本

  對(duì)于每個(gè)查詢計(jì)劃和執(zhí)行上下文,都會(huì)保留一個(gè)成本。該成本會(huì)在一定程度上控制計(jì)劃或上下文在計(jì)劃緩存中的存在時(shí)間。在 sql server 2000 和 sql server 2005 中,成本的計(jì)算和操作方式有所不同。詳細(xì)情況如下。

  sql server 2000:對(duì)于查詢計(jì)劃,成本用于度量查詢優(yōu)化器用于優(yōu)化批處理的服務(wù)器資源(cpu 時(shí)間和 i/o)。對(duì)于特殊查詢,其成本為零。對(duì)于執(zhí)行上下文,成本用于度量用于初始化執(zhí)行上下文以便各個(gè)語句做好執(zhí)行準(zhǔn)備的服務(wù)器資源(cpu 時(shí)間和 i/o)。請(qǐng)注意,執(zhí)行上下文成本并不包含批處理執(zhí)行期間所帶來的成本(cpu 和 i/o)。通常,執(zhí)行上下文成本低于查詢計(jì)劃成本。

  以下說明了在 sql server 2000 中,批處理的查詢計(jì)劃如何帶來成本開銷。影響成本的因素有四個(gè):生成計(jì)劃所用的 cpu 時(shí)間 (cputime);從磁盤讀取的頁數(shù) (ioread);寫入磁盤的頁數(shù) (iowrite);以及批處理的查詢計(jì)劃所占的內(nèi)存頁數(shù) (pagecount)。這樣,查詢計(jì)劃成本可表示為(f 是一個(gè)數(shù)學(xué)函數(shù)):

query plan cost c = f(cputime, ioread, iowrite) / pagecount

  以下說明了在 sql server 2000 中,批處理的執(zhí)行上下文如何帶來成本開銷。上方等式中單獨(dú)的成本 c 將針對(duì)批處理中的每個(gè)語句進(jìn)行計(jì)算,并加以累計(jì)。但是請(qǐng)注意,單獨(dú)成本現(xiàn)在是語句初始化成本,而非語句編譯或執(zhí)行成本。

  有時(shí),惰性寫入器進(jìn)程會(huì)清除計(jì)劃緩存并減少成本。將成本除于四,并根據(jù)需要四舍五入。(例如,25 --> 6 --> 1 --> 0。)當(dāng)內(nèi)存方面有壓力時(shí),成本為零的查詢計(jì)劃和執(zhí)行上下文將從計(jì)劃緩存中刪除。重用查詢計(jì)劃或執(zhí)行上下文時(shí),其成本會(huì)被重置回編譯(或執(zhí)行上下文生成)成本。特殊查詢的查詢計(jì)劃成本總是以 1 為單位逐漸遞增。因此,頻繁執(zhí)行的批處理的查詢計(jì)劃在計(jì)劃緩存中的存在時(shí)間要長于不頻繁執(zhí)行的批處理的計(jì)劃。

  sql server 2005:特殊查詢的成本為零。另外,查詢計(jì)劃的成本用于度量生成其所需的資源量。尤其,該成本按“記號(hào)數(shù)”計(jì)算,最大值為 31,共由三部分組成:

  成本 = i/o 成本 + 上下文開關(guān)成本(用于度量 cpu 成本) + 內(nèi)存成本

  該成本各部分的計(jì)算方法如下。

  兩個(gè) i/o 的成本為 1 個(gè)記號(hào),最大成本為 19 個(gè)記號(hào)。

  另個(gè)上下文開關(guān)的成本為 1 個(gè)記號(hào),最大成本為 8 個(gè)記號(hào)。

  十六個(gè)內(nèi)存頁 (128 kb) 的成本為 1 個(gè)記號(hào),最大成本為 4 個(gè)記號(hào)。

  在 sql server 2005 中,計(jì)劃緩存不同于數(shù)據(jù)緩存。此外,還有一些特定于功能的緩存。在 sql server 2005 中,惰性寫入器進(jìn)程不會(huì)增加成本。相反,只要計(jì)劃緩存的大小達(dá)到緩沖池大小的 50%,下一個(gè)計(jì)劃緩存訪問就會(huì)以 1 為單位減少所有計(jì)劃的記號(hào)數(shù)。請(qǐng)注意,由于這種減少情況是隨為查找計(jì)劃而訪問計(jì)劃緩存的線程而產(chǎn)生的,因此可認(rèn)為這一減少是以惰性方式進(jìn)行的。在 sql server 2005 中,如果所有緩存大小的總和達(dá)到或超過了緩沖池大小的 75%,那么將激活一個(gè)專用的資源監(jiān)視器線程,它將減少所有緩存中的所有對(duì)象的記號(hào)數(shù)。(所以該線程的行為方式與 sql server 2000 中的惰性寫入器線程大致相同。)查詢計(jì)劃重用導(dǎo)致查詢計(jì)劃成本被重置為初識(shí)值。

  五、文本其他部分的內(nèi)容說明

  到此,讀者應(yīng)該清楚:為了獲得良好的 sql server 批處理執(zhí)行性能,需要執(zhí)行下列這兩項(xiàng)操作:

  應(yīng)盡可能重用查詢計(jì)劃。這可避免不必要的查詢編譯成本。計(jì)劃重用還會(huì)帶來更高的計(jì)劃緩存使用率,而反過來又會(huì)實(shí)現(xiàn)更好的服務(wù)器性能。

  應(yīng)避免可能造成查詢編譯次數(shù)增多的操作。減少重新編譯次數(shù)可節(jié)省服務(wù)器資源(cpu 和內(nèi)存),并增加批處理執(zhí)行次數(shù),同時(shí)達(dá)到預(yù)期性能。

  下一節(jié)描述了有關(guān)查詢計(jì)劃重用的詳細(xì)信息。同時(shí),在適當(dāng)位置給出了可實(shí)現(xiàn)更好的計(jì)劃重用的最佳實(shí)務(wù)。再下一節(jié)中,我們介紹了可能導(dǎo)致重新編譯次數(shù)增多的一些常見方案,并給出了避免發(fā)生這種情況的最佳實(shí)務(wù)。

六、查詢計(jì)劃重用

  計(jì)劃緩存包含查詢計(jì)劃和執(zhí)行上下文。概念上,查詢計(jì)劃同與之相關(guān)聯(lián)的執(zhí)行上下文相鏈接。批處理 s 的查詢計(jì)劃重用獨(dú)立于 s 本身(比如:查詢文本或存儲(chǔ)過程名稱)以及該批處理的一些外部因素(比如:生成 s 的用戶名,生成 s 的 set 選項(xiàng),與 s 相關(guān)聯(lián)的連接的 set 選項(xiàng)等等)。有一些外部因素會(huì)影響計(jì)劃重用:只要兩個(gè)相同的查詢?cè)谶@些因素之一上有所不同,就將無法使用常見計(jì)劃。而其他外部因素則不會(huì)影響計(jì)劃重用。

  大多數(shù)影響計(jì)劃重用的因素都羅列在 sys.syscacheobjects 虛擬表中。下方列表描述了“典型用法”方案中的因素。在某些情況下,條目只會(huì)指出何時(shí)計(jì)劃未被緩存(并因此永不被重用)。

  通常,如果導(dǎo)致查詢計(jì)劃被緩存的連接的服務(wù)器、數(shù)據(jù)庫和連接設(shè)置與當(dāng)前連接的相應(yīng)設(shè)置相同,就會(huì)重用查詢計(jì)劃。其次,批處理所引用的對(duì)象不要求名稱解析。例如,sales.salesorderdetail 不要求名稱解析,而 salesorderdetail 則相反,因?yàn)槊麨?salesorderdetail 的表會(huì)存在于多個(gè)數(shù)據(jù)庫中。大體上,完全合格的對(duì)象名稱會(huì)為計(jì)劃重用提供更多的機(jī)會(huì)。

影響計(jì)劃重用的因素

  請(qǐng)注意,查詢計(jì)劃如果還未被緩存,就不能被重用。 所以,我們將僅明確指出無可緩存性,即表示無重用。

  1.

  如果一個(gè)存儲(chǔ)過程在數(shù)據(jù)庫 d1 中執(zhí)行,那么在不同的數(shù)據(jù)庫 d2 中執(zhí)行相同的存儲(chǔ)過程時(shí),就不會(huì)重用其查詢計(jì)劃。請(qǐng)注意,這一行為僅適用于存儲(chǔ)過程,并不適用于特殊查詢、預(yù)備的查詢或動(dòng)態(tài) sql。

  2.

  對(duì)于觸發(fā)器執(zhí)行,受執(zhí)行影響的行數(shù)(1 比 n)——按被插入或被刪除的表中的行數(shù)度量——是確定計(jì)劃緩存命中的一個(gè)顯著因素。請(qǐng)注意,該行為特別針對(duì)觸發(fā)器,并不適用于存儲(chǔ)過程。

  在 sql server 2005 instead of 觸發(fā)器中,“1-plan”由影響 0 和 1 行的執(zhí)行共享,而對(duì)于 non-instead of ("after") 觸發(fā)器,“1-plan”僅由影響 1 行的執(zhí)行使用,同時(shí)“n-plan”由影響 0 和 n 行 (n > 1) 的執(zhí)行使用。

  3.

  從不緩存大容量插入語句,但卻緩存與大容量插入相關(guān)聯(lián)的觸發(fā)器。

  4.

  不緩存包含任何長于 8 kb 的文本的批處理。因此,無法緩存這種批處理的查詢計(jì)劃。(應(yīng)用常量折疊之后,測量文本的長度。)

  5.

  標(biāo)有“復(fù)制標(biāo)記”(與某位復(fù)制用戶相關(guān)聯(lián))的批處理與沒有該標(biāo)記的批處理不相匹配。

  6.

  從 sql server 2005 的通用語言運(yùn)行時(shí) (clr) 調(diào)用的批處理與從 clr 外部提交的相同批處理不相匹配。然而,兩個(gè)由 clr 提交的批處理可重用相同的計(jì)劃。相同的情況適用于:

  clr 觸發(fā)器和非-clr 觸發(fā)器

  通知查詢和非通知查詢

  7.

  不緩存通過 sp_resyncquery 提交的查詢的查詢計(jì)劃。所以,如果重新提交了(通過或不通過 sp_resyncquery 提交)該查詢,就需要重新進(jìn)行編譯。

  8.

  sql server 2005 允許在 t-sql 批處理上定義游標(biāo)。如果批處理被當(dāng)作單獨(dú)的語句提交,那么就不會(huì)對(duì)游標(biāo)重用(部分)計(jì)劃。

  9.

  下列 set 選項(xiàng)會(huì)影響計(jì)劃重用。

編號(hào)set 選項(xiàng)名

  1

  ansi_null_dflt_off

  2

  ansi_null_dflt_on

  3

  ansi_nulls

  4

  ansi_padding

  5

  ansi_warnings

  6

  arithabort

  7

  concat_null_yields_null

  8

  datefirst

  9

  dateformat

  10

  forceplan

  11

  language

  12

  no_browsetable

  13

  numeric_roundabort

  14

  quoted_identifier

  此外,ansi_defaults 也會(huì)影響計(jì)劃重用,因?yàn)槠淇捎糜谕瑫r(shí)更改下列 set 選項(xiàng)(其中有一些會(huì)影響計(jì)劃重用):ansi_nulls、ansi_null_dflt_on、ansi_padding、ansi_warnings、cursor_close_on_commit、implicit_transactions、quoted_identifier.

  上面這些 set 選項(xiàng)會(huì)影響計(jì)劃重用,因?yàn)?sql server 2000 和 sql server 2005 都能執(zhí)行“常量折疊”(在編譯時(shí)評(píng)估常量表達(dá)式以實(shí)現(xiàn)一些優(yōu)化),而且這些選項(xiàng)的設(shè)置會(huì)影響這類表達(dá)式的結(jié)果。

  部分上述 set 選項(xiàng)的設(shè)置羅列在 sys.syscacheobjects 虛擬表中(比如:“langid”和“dateformat”。

  請(qǐng)注意,可使用幾種方法更改部分上述 set 選項(xiàng)的值:

  使用 sp_configure 存儲(chǔ)過程(針對(duì)服務(wù)器范圍的更改)

  使用 sp_dboption 存儲(chǔ)過程(針對(duì)數(shù)據(jù)庫范圍的更改)

  使用 alter database 語句的 set 子句

  在 set 選項(xiàng)存在沖突時(shí),用戶級(jí)和連接級(jí) set 選項(xiàng)值優(yōu)先于數(shù)據(jù)庫和服務(wù)器級(jí) set 選項(xiàng)值。另外,如果某個(gè)數(shù)據(jù)庫級(jí) set 選項(xiàng)有效,那么對(duì)于引用多個(gè)數(shù)據(jù)庫(可能擁有不同的 set 選項(xiàng)值)的批處理,數(shù)據(jù)庫(該批處理在其上下文中執(zhí)行)的 set 選項(xiàng)優(yōu)先于其他數(shù)據(jù)庫的 set 選項(xiàng)。

  最佳實(shí)務(wù):為了避免與 set 選項(xiàng)相關(guān)的重新編譯,在連接時(shí)創(chuàng)建 set 選項(xiàng),并確保其在連接期間不會(huì)發(fā)生變化。

  10.

  帶有不合格對(duì)象名的批處理不會(huì)重用查詢計(jì)劃。例如,在“select * from mytable”中,如果 alice 發(fā)出了相應(yīng)的查詢并擁有帶有相應(yīng)名稱的表,mytable 可能會(huì)正常地解析到 alice。同樣,mytable 可能解析到 bob.mytable。在這種情況下,sql server 不會(huì)重用查詢計(jì)劃。但是,如果 alice 發(fā)出了“select * from dbo.mytable”,就不會(huì)存在不確定性,因?yàn)閷?duì)象被唯一指定,并可重用查詢計(jì)劃。(請(qǐng)參見 sys.syscacheobjects 中的 uid 列。該列給出了生成計(jì)劃的連接的用戶 id。只有帶有相同用戶 id 的查詢計(jì)劃才可被重用。當(dāng) uid = -2 時(shí),表示該查詢不依賴于隱式名稱解析,并可在不同的用戶 id 間共享。)

  11.

  當(dāng)通過“create procedure ...with recompile”選項(xiàng)創(chuàng)建存儲(chǔ)過程時(shí),無論何時(shí)執(zhí)行該存儲(chǔ)過程,都不會(huì)緩存其查詢計(jì)劃。不存在計(jì)劃重用的可能性:每次執(zhí)行這種過程都會(huì)導(dǎo)致重新編譯。

  12.

  最佳實(shí)務(wù):“create procedure ...with recompile”可用于標(biāo)記通過各種參數(shù)調(diào)用的存儲(chǔ)過程,而其最佳的查詢計(jì)劃高度依賴于在調(diào)用期間所提供的參數(shù)值。

  13.

  當(dāng)使用“exec ...with recompile”執(zhí)行存儲(chǔ)過程 p 時(shí),p 被重新編譯。即使 p 的一個(gè)查詢計(jì)劃預(yù)先存在于計(jì)劃緩存中并可被重用,也不會(huì)發(fā)生重用。不緩存為 p 全新編譯的查詢計(jì)劃。

  最佳實(shí)務(wù):當(dāng)通過非典型參數(shù)值執(zhí)行存儲(chǔ)過程時(shí),“exec ...with recompile”可用于確保新的查詢計(jì)劃不會(huì)替代使用典型參數(shù)值編譯的現(xiàn)有的已緩存計(jì)劃。

  “exec ...with recompile”還可與用戶定義的函數(shù)一起使用,但只有在存在 exec 關(guān)鍵字時(shí)才可以。

  1.

  為了避免通過不同的參數(shù)值執(zhí)行的查詢存在多個(gè)查詢計(jì)劃,應(yīng)使用 sp_executesql 存儲(chǔ)過程執(zhí)行該查詢。如果同一個(gè)查詢計(jì)劃有益于所有或大多數(shù)參數(shù)值,那么這種方法將很有用。

  2.

  可緩存臨時(shí)存儲(chǔ)過程(針對(duì)會(huì)話范圍及全局),因而可進(jìn)行重用。

  3.

  在 sql server 2005 中,不緩存創(chuàng)建或更新統(tǒng)計(jì)(手動(dòng)或自動(dòng))的查詢的計(jì)劃。

七、導(dǎo)致重新編譯的原因

  回想一下,當(dāng) sql server 在批處理 b 中執(zhí)行語句后,重新編譯了某些(或所有)語句,這時(shí) b 被重新編譯。產(chǎn)生重新編譯的原因可分為兩大類:

  與正確性相關(guān)的原因。如果不進(jìn)行重新編譯會(huì)導(dǎo)致錯(cuò)誤的結(jié)果或操作,那么就必須對(duì)批處理進(jìn)行重新編譯。與正確性相關(guān)的原因又可分為兩類。

  對(duì)象的架構(gòu)。 批處理 b 可能會(huì)引用許多對(duì)象(表、視圖、索引、統(tǒng)計(jì)、udf 等等),而如果自 b 上次編譯后,某些對(duì)象的架構(gòu)發(fā)生了變化,那么就需要重新編譯 b 以保證語句正確。

  set 選項(xiàng)。 一些 set 選項(xiàng)會(huì)影響查詢結(jié)果。如果某個(gè)影響計(jì)劃重用的 set 選項(xiàng)的設(shè)置在批處理內(nèi)被更改,就會(huì)發(fā)生重新編譯。

  與計(jì)劃最優(yōu)性相關(guān)的原因。自 b 上次編譯之后,b 所引用的表中的數(shù)據(jù)可能發(fā)生巨大的變化。在這種情況下,可能會(huì)對(duì) b 進(jìn)行重新編譯,以便獲得更快捷的查詢執(zhí)行計(jì)劃。

  下面兩節(jié)將詳細(xì)介紹這兩個(gè)類別。

導(dǎo)致批處理重新編譯的與正確性相關(guān)的原因

  后面列舉了一些導(dǎo)致與正確性相關(guān)的重新編譯的具體操作。因?yàn)楸仨氝M(jìn)行這類重新編譯,所以用戶可以選擇不進(jìn)行這些操作,或者在 sql server 運(yùn)行的非高峰期執(zhí)行這些操作。

對(duì)象的架構(gòu)

  1.

  無論批處理引用的任何對(duì)象在何時(shí)發(fā)生了架構(gòu)更改,批處理都會(huì)被重新編譯。“架構(gòu)更改”的定義如下:

  將列添加或放到表或視圖中

  將約束、默認(rèn)值或規(guī)則添加或放到表中,或者進(jìn)行相反操作

  將索引添加到表或索引視圖中

  放置表或索引視圖上定義的索引(只要該索引被相應(yīng)的查詢計(jì)劃所用)

  (sql server 2000)。手動(dòng)在表上更新或放置統(tǒng)計(jì)(不是創(chuàng)建!)將導(dǎo)致重新編譯任何使用該表的查詢計(jì)劃。上述查詢計(jì)劃將下次開始執(zhí)行時(shí)進(jìn)行重新編譯。

  (sql server 2005)。手動(dòng)創(chuàng)建或放置表上定義的統(tǒng)計(jì)(不是更新!)將導(dǎo)致重新編譯任何使用該表的查詢計(jì)劃(借助表架構(gòu)版本更改來實(shí)現(xiàn))。上述查詢計(jì)劃將下次開始執(zhí)行時(shí)進(jìn)行重新編譯。

  請(qǐng)注意,在 sql server 2000 或 sql server 2005 中,自動(dòng)創(chuàng)建或自動(dòng)更新的統(tǒng)計(jì)不會(huì)導(dǎo)致架構(gòu)更改,但會(huì)強(qiáng)制進(jìn)行與正確性相關(guān)的重新編譯。在 sql server 2005 中,相同的語句適用于手動(dòng)更新的統(tǒng)計(jì)。但是,這些操作會(huì)導(dǎo)致與計(jì)劃最優(yōu)性相關(guān)的重新編譯(針對(duì)載入這些統(tǒng)計(jì)的查詢計(jì)劃),第 7.2 節(jié)對(duì)此有所詳細(xì)描述。

  2.

  在存儲(chǔ)過程或觸發(fā)器上運(yùn)行 sp_recompile 會(huì)導(dǎo)致它們?cè)谙乱淮螆?zhí)行時(shí)被重新編譯。在表或視圖上運(yùn)行 sp_recompile 時(shí),所有引用該表或視圖的存儲(chǔ)過程都將在下一次運(yùn)行時(shí)被重新編譯。sp_recompile 通過遞增上述對(duì)象的磁盤上的架構(gòu)版本來完成重新編譯。

  3.

  下列操作會(huì)刷新整個(gè)計(jì)劃緩存,從而導(dǎo)致對(duì)之后所提交的批處理進(jìn)行全新編譯:

  分離數(shù)據(jù)庫

  將數(shù)據(jù)庫升級(jí)到 sql server 2000(在 sql server 2000 上)

  將數(shù)據(jù)庫升級(jí)到 sql server 2005(在 sql server 2005 服務(wù)器上)

  dbcc freeproccache 命令

  reconfigure 命令

  alter database ...modify filegroup 命令

  使用 alter database ... 修改排序collate 命令

  下列操作將刷新引用特定數(shù)據(jù)庫的計(jì)劃緩存條目,并隨之導(dǎo)致全新編譯。

  dbcc flushprocindb 命令

  alter database ...modify name = 命令

  alter database ...set online 命令

  alter database ...set offline 命令

  alter database ...set emergency 命令

  drop database 命令

  數(shù)據(jù)庫自動(dòng)關(guān)閉時(shí)

  當(dāng)通過 check option 創(chuàng)建視圖時(shí),在其中創(chuàng)建該視圖的數(shù)據(jù)庫的計(jì)劃緩存條目將被刷新。

  運(yùn)行 dbcc checkdb 時(shí),將創(chuàng)建指定數(shù)據(jù)庫的一個(gè)副本。作為 dbcc checkdb 執(zhí)行的一部分,將執(zhí)行針對(duì)該副本的一些查詢,并緩存其計(jì)劃。在 dbcc checkdb 執(zhí)行結(jié)束時(shí),將刪除該副本以及針對(duì)其的查詢的查詢計(jì)劃。

  “引用特定數(shù)據(jù)庫的計(jì)劃緩存條目”這一概念需要解釋一下。數(shù)據(jù)庫 id 是計(jì)劃緩存的鍵之一。假設(shè)執(zhí)行了下列命令序列。

use master
go
<-- a query q that references a database called db1 -->
go

  假定在計(jì)劃緩存中緩存了 q。與 q 的計(jì)劃相關(guān)聯(lián)的數(shù)據(jù)庫 id 將成為“master”而非“db1”的數(shù)據(jù)庫 id。

  當(dāng) sql server 2005 的事務(wù)級(jí)快照隔離級(jí)別開啟時(shí),通常會(huì)發(fā)生計(jì)劃重用。只要快照隔離級(jí)別下的批處理中的語句引用了一個(gè)對(duì)象(其架構(gòu)自開啟快照隔離模式后即被更改),同時(shí)緩存并重用了該語句的查詢計(jì)劃,就會(huì)發(fā)生語句級(jí)重新編譯。全新編譯的查詢計(jì)劃將被緩存,而該語句本身則會(huì)失敗(根據(jù)相應(yīng)隔離級(jí)別的語義)。如果未緩存查詢計(jì)劃,就會(huì)發(fā)生編譯,隨后被編譯的查詢計(jì)劃會(huì)被緩存,而語句本身則會(huì)失敗。

set 選項(xiàng)

  正如第 6 節(jié)已經(jīng)提到的,在批處理開始執(zhí)行后更改下列 set 選項(xiàng)中的一項(xiàng)或多項(xiàng),將導(dǎo)致重新編譯:ansi_null_dflt_off、ansi_null_dflt_on、ansi_nulls、ansi_padding、ansi_warnings、arithabort、concat_null_yields_null、datefirst、dateformat、forceplan、language、no_browsetable、numeric_roundabort、quoted_identifier。

導(dǎo)致批處理重新編譯的與計(jì)劃最優(yōu)性相關(guān)的原因

  sql server 設(shè)計(jì)用于當(dāng)數(shù)據(jù)庫中的數(shù)據(jù)更改時(shí),生成最佳的查詢執(zhí)行計(jì)劃。使用 sql server 的查詢處理器中的統(tǒng)計(jì)(直方圖)來跟蹤數(shù)據(jù)更改。所以,與計(jì)劃最優(yōu)性相關(guān)的原因同統(tǒng)計(jì)密切相關(guān)。

  開始詳細(xì)介紹與計(jì)劃最優(yōu)性相關(guān)的原因之前,讓我們列出不會(huì)發(fā)生與計(jì)劃最優(yōu)性相關(guān)的重新編譯的情況。

  當(dāng)計(jì)劃屬于“常用計(jì)劃”時(shí)。當(dāng)查詢優(yōu)化器決定查詢所引用的給定表及其上的索引時(shí),將產(chǎn)生常用計(jì)劃,只能有一個(gè)計(jì)劃。顯而易見,在這種情況下進(jìn)行重新編譯并沒有什么用。當(dāng)然,生成過常用計(jì)劃的查詢不一定總是生成這類計(jì)劃。例如,可能在基礎(chǔ)表上創(chuàng)建新的索引,從而就有多個(gè)訪問路徑供查詢優(yōu)化器使用。如第 7.1 節(jié)所提到的,所添加的這類索引將被刪除,而與正確性相關(guān)的重新編譯可能將常用計(jì)劃替換為非常用計(jì)劃。

  當(dāng)查詢包含“keepfixed plan”提示時(shí),不會(huì)出于與計(jì)劃最優(yōu)性相關(guān)的原因重新編譯該查詢的計(jì)劃。

  當(dāng)查詢計(jì)劃引用的所有表都為只讀時(shí),該計(jì)劃將被重新編譯。

  這一點(diǎn)只適用于 sql server 2000。假定某個(gè)查詢計(jì)劃被編譯(不是重新編譯),而作為編譯的一部分,查詢處理器將決定更新表 t 上的統(tǒng)計(jì) s。查詢處理器試圖在 t 上獲取一個(gè)特殊的“統(tǒng)計(jì)鎖”。如果其他進(jìn)程正在更新 t 上的某個(gè)統(tǒng)計(jì)(不一定是 s!),查詢處理器就無法在 t 上獲得統(tǒng)計(jì)鎖。在這種情況下,查詢處理器不會(huì)更新 s。另外,上述查詢計(jì)劃不會(huì)再因?yàn)榕c計(jì)劃最優(yōu)性相關(guān)的原因而被重新編譯。這就像通過“keepfixed plan”提示提交查詢一樣。

  這種情況與上面著重提到的一個(gè)情況相同,只是此處的查詢計(jì)劃被緩存了。換句話說,這種情況涉及重新編譯,而前面的那個(gè)情況與之相反,僅涉及編譯。對(duì)于這種重新編譯情形,假設(shè)查詢處理器試圖在 t 上獲得一個(gè)“統(tǒng)計(jì)鎖”,但失敗了。在這種情況下,查詢處理器會(huì)跳過對(duì)統(tǒng)計(jì) s 的更新;使用過時(shí)的統(tǒng)計(jì) s;并同平常一樣,通過其他重新編譯步驟/檢查繼續(xù)進(jìn)行操作。因而,借助可能較慢的查詢執(zhí)行計(jì)劃可避免重新編譯。

深入介紹查詢編譯

  下方流程圖簡單明了地描述了 sql server 中的批處理編譯和重新編譯過程。主要的處理步驟如下所示(本文檔后面將對(duì)各個(gè)步驟進(jìn)行詳細(xì)介紹):

  1.

  sql server 開始編譯一個(gè)查詢。(正如前面提到的,批處理是一個(gè)編譯和緩存單位,而批處理中的各個(gè)語句則是逐一進(jìn)行編譯。)

  2.

  可能有助于生成最佳查詢計(jì)劃的所有“引起關(guān)注的”統(tǒng)計(jì)都將從磁盤載入內(nèi)存。

  3.

  如果任何統(tǒng)計(jì)過時(shí)了,那么將逐一對(duì)其進(jìn)行更新。查詢編譯將等待更新的結(jié)束。對(duì)于這一步驟,sql server 2000 和 sql server 2005 間的一個(gè)重要不同之處在于:在 sql server 2005 中,可能會(huì)有選擇地對(duì)統(tǒng)計(jì)進(jìn)行異步更新。也就是說,統(tǒng)計(jì)更新線程不阻止查詢編譯線程。編譯線程將用狀態(tài)統(tǒng)計(jì)繼續(xù)操作。

  4.

  生成查詢計(jì)劃。查詢中所引用的所有表的重新編譯閾值隨查詢計(jì)劃一起被保存。

  5.

  這時(shí),查詢執(zhí)行在理論上已經(jīng)開始。現(xiàn)在測試查詢計(jì)劃以查找與正確性相關(guān)的原因。相關(guān)原因在第 7.1 中有所描述。

  6.

  如果就任何與正確性相關(guān)的原因而言,計(jì)劃不正確,那么將開始進(jìn)行重新編譯。請(qǐng)注意,由于查詢執(zhí)行在理論上已經(jīng)開始了,因此剛剛開始的編譯即為重新編譯。

  7.

  如果計(jì)劃“正確”,那么各種重新編譯閾值將與表基數(shù)或各種表修改計(jì)數(shù)器(sql server 2000 中的 rowmodctr 或 sql server 2005 中的 colmodctr)相比較。

  8.

  如果根據(jù)步驟 7 中進(jìn)行的比較認(rèn)定有任何統(tǒng)計(jì)過時(shí)了,那么將進(jìn)行重新編譯。

  9.

  如果步驟 7 中的所有比較都成功完成,那么將開始實(shí)際的查詢執(zhí)行。

與計(jì)劃最優(yōu)性相關(guān)的重新編譯:整體情況

  每個(gè) select、insert、update 和 detele 語句都訪問一個(gè)或多個(gè)表。表內(nèi)容因 insert、update 和 delete 等操作而發(fā)生變化。sql server 的查詢處理器設(shè)計(jì)用于通過潛在地生成不同的查詢計(jì)劃(每個(gè)查詢計(jì)劃在生成時(shí)都是最佳的),來適應(yīng)這種變化。使用表基數(shù)直接跟蹤表內(nèi)容,并使用表列上的統(tǒng)計(jì)(直方圖)進(jìn)行間接跟蹤。

  每個(gè)表都有一個(gè)與之相關(guān)聯(lián)的重新編譯閾值 (rt)。rt 是表中列數(shù)的一個(gè)函數(shù)。在查詢編譯期間,查詢處理器將不載入或載入若干個(gè)在查詢中引用的表上的統(tǒng)計(jì)。這些統(tǒng)計(jì)被稱為引人關(guān)注的統(tǒng)計(jì)。對(duì)于查詢中引用的每個(gè)表,已編譯的查詢計(jì)劃包含:

  重新編譯閾值

  列出查詢編譯期間載入的所有統(tǒng)計(jì)的列表對(duì)于每個(gè)統(tǒng)計(jì),將保存計(jì)算表修改次數(shù)的計(jì)數(shù)器的快照值。在 sql server 2000 中,該計(jì)數(shù)器被稱為 rowmodctr,而在 sql server 2005 中則稱為 colmodctr。每個(gè)表列中都存在一個(gè)單獨(dú)的 colmodctr(非永久性計(jì)算列除外)。

閾值交叉測試——執(zhí)行其用于決定是否要重新編譯查詢計(jì)劃——由下列公式定義:| modctr(snapshot) – modctr(current) | >= rt

  modctr(current) 表示修改計(jì)數(shù)器的當(dāng)前值,而 modctr(snapshot) 表示查詢計(jì)劃上次編譯時(shí)修改計(jì)數(shù)器的值。如果閾值交叉在任何令人關(guān)注的統(tǒng)計(jì)上取得了成功,那么將重新編譯查詢計(jì)劃。在 sql server 2000 中,包含該查詢的整個(gè)批處理都被重新編譯;而在 sql server 2005 中,僅重新編譯上述查詢。

  如果表或索引視圖 t 上沒有統(tǒng)計(jì),或者在查詢編譯期間 t 上現(xiàn)有的統(tǒng)計(jì)都不被認(rèn)為是“令人關(guān)注的”,那么仍會(huì)僅根據(jù) t 的基數(shù),執(zhí)行下列閾值交叉測試。

| card(snapshot) – card(current) | >= rt

  card(current) 表示當(dāng)前 t 中的行數(shù),而 card(snapshot) 表示查詢計(jì)劃上次編譯時(shí)的行數(shù)。

  下面幾節(jié)將介紹“整體情況”中引入的幾個(gè)重要概念。

“令人關(guān)注”的統(tǒng)計(jì)的概念

  對(duì)于每個(gè)查詢計(jì)劃 p,優(yōu)化器保存被載入以生成 p 的統(tǒng)計(jì)的 id。請(qǐng)注意,“載入的”集同時(shí)包含:

  用作操作符(顯示在 p 中的)的基數(shù)評(píng)估器的統(tǒng)計(jì)

  用作查詢計(jì)劃(在查詢優(yōu)化期間加以考慮但為了支持 p 而被拋棄)中的基數(shù)評(píng)估器的統(tǒng)計(jì)

  換而言之,查詢優(yōu)化器出于某個(gè)原因或其他原因,將載入的統(tǒng)計(jì)認(rèn)作是“令人關(guān)注的”。

  回想一下,統(tǒng)計(jì)可以手動(dòng)或自動(dòng)創(chuàng)建或更新。還會(huì)因執(zhí)行下列命令而導(dǎo)致統(tǒng)計(jì)更新:

  create index ...with drop existing

  sp_createstats 存儲(chǔ)過程

  sp_updatestats 存儲(chǔ)過程

  dbcc dbreindex(但不是 dbcc indexdefrag!)

重新編譯閾值 (rt)

  表的重新編譯閾值可部分決定引用該表的查詢的重新編譯頻率。rt 取決于表類型(永久或臨時(shí))以及編譯查詢計(jì)劃時(shí)表中的行數(shù)(基數(shù))。在批處理中引用的所有表的重新編譯閾值都將隨該批處理的查詢計(jì)劃一起保存。

  rt 的計(jì)算方法如下所示。(n 表示編譯查詢計(jì)劃時(shí)表的基數(shù)。)

  永久表

  如果 n<=500,則 rt = 500。

  如果 n>500,則 rt = 500 + 0.20 * n。

  臨時(shí)表

  如果 n<6,則 rt = 6。

  如果 6<=n<=500,則 rt = 500。

  如果 n > 500,則 rt = 500 + 0.20 * n。

  表變量

  不存在 rt。所以,由于表變量的基數(shù)發(fā)生了變化而不會(huì)產(chǎn)生重新編譯。

  表修改計(jì)數(shù)器(rowmodctr 和 colmodctr)

  如上所述,rt 與表所執(zhí)行的修改次數(shù)進(jìn)行了對(duì)比。使用稱為 rowmodctr(在 sql server 2000 中)和 colmodctr(在 sql server 2005 中)的計(jì)數(shù)器跟蹤表所進(jìn)行的修改次數(shù)。 這兩種計(jì)數(shù)器都不是針對(duì)具體事務(wù)的。例如,如果啟動(dòng)了某個(gè)事務(wù),并在表中插入了 100 行,然后再回滾操作,那么對(duì)修改計(jì)數(shù)器所作的更改將不會(huì)被回滾。

rowmodctr (sql server 2000)

  每個(gè)表都有一個(gè) rowmodctr 與之相關(guān)聯(lián)。其值可從 sysindexes 系統(tǒng)表獲得。在表或索引視圖 t 的一個(gè)或多個(gè)列上創(chuàng)建的每個(gè)統(tǒng)計(jì)都有一個(gè) rowmodctr 的快照值與之相關(guān)聯(lián)。無論該統(tǒng)計(jì)何時(shí)被更新——手動(dòng)或自動(dòng)(通過 sql server 的自動(dòng)統(tǒng)計(jì)功能),rowmodctr 的快照值也會(huì)被刷新。有關(guān) rowmodctr 的詳細(xì)信息在下方白皮書中有所描述:http://msdn.microsoft.com/library/default.asp?url=/nhp/default.asp?contentid=28000409

  “閾值交叉”測試中所提到的 rowmodctr(current) 是 sysindexes 系統(tǒng)表(針對(duì)堆棧或聚集索引)在查詢編譯期間進(jìn)行測試時(shí)所保留的值。

  rowmodctr 可在 sql server 2005 服務(wù)器上使用,但其值總為 0。

  補(bǔ)充說明一下,在 sql server 2000 中,當(dāng) rowmodctr 為 0 時(shí),將無法導(dǎo)致重新編譯。

colmodctr (sql server 2005)

  與 rowmodctr 不同,每個(gè)表列都會(huì)保存一個(gè) colmodctr 值(非永久性計(jì)算列除外)。同普通列一樣,永久性計(jì)算列擁有 colmodctr。使用 colmodctr 值,可以更細(xì)化地跟蹤表的更改。colmodctr 值對(duì)用戶不可用;僅供查詢處理器使用。

  當(dāng)在表或索引視圖 t 的一個(gè)或多個(gè)列上(通過自動(dòng)統(tǒng)計(jì)功能手動(dòng)或自動(dòng))創(chuàng)建或更新統(tǒng)計(jì)時(shí),最左邊一列的 colmodctr 的快照值將保存在統(tǒng)計(jì)二進(jìn)制大對(duì)象 (stats-blob) 中。

  “閾值交叉”測試中所提到的 colmodctr(current) 在查詢編譯期間進(jìn)行測試時(shí)保留在 sql server 2005 的元數(shù)據(jù)中的值。

  與 rowmodctr 不同,colmodctr 的值是一個(gè)不斷遞增的序列:colmodctr 值從不被重置為 0。

  不存在非永久性計(jì)算列的 colmodctr 值。其派生自參與計(jì)算的列。

使用 rowmodctr 和 colmodctr 跟蹤表和索引視圖的更改

  由于 rowmodctr 和 colmodctr 值用于做出重新編譯決定,因此它們的值被當(dāng)作表更改來進(jìn)行修改。在下列描述中,我們僅提到了表。但是,相同的情況也適用于索引視圖。可通過下列語句更改表:insert、delete、update、大容量插入和表截?cái)唷O铝斜矶x了修改 rowmodctr 和 colmodctr 值的方式。

語句sql server 2000sql server 2005

  insert

  rowmodctr += 1

  所有 colmodctr += 1

  delete

  rowmodctr += 1

  所有 colmodctr += 1

  update

  rowmodctr += 2 或 3。“2”的說明:1 表示刪除 + 1 表示插入。

  如果更新針對(duì)非鍵列:colmodctr += 1 針對(duì)所有已更新的列。

  如果更新針對(duì)鍵列:colmodctr += 2 針對(duì)所有列。

  大容量插入

  不更改。

  與 n insert 相同。所有 colmodctr += n。(n 是大容量插入的行數(shù)。)

  表截?cái)?/p>

  不更改。

  與 n delete 相同。所有 colmodctr += n。(n 是表的基數(shù)。)

  ,歡迎訪問網(wǎng)頁設(shè)計(jì)愛好者web開發(fā)。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 龙江县| 米林县| 西林县| 西安市| 永修县| 博野县| 东辽县| 衡东县| 招远市| 孝义市| 德江县| 扬中市| 龙胜| 上饶县| 青州市| 澄迈县| 霍林郭勒市| 定安县| 浦县| 南岸区| 青海省| 灌南县| 通化市| 铁力市| 黄山市| 邹平县| 固始县| 凭祥市| 武宁县| 天镇县| 怀安县| 资阳市| 北辰区| 郓城县| 彰化县| 沈阳市| 饶河县| 靖州| 外汇| 安顺市| 敖汉旗|