編譯的含義
當sqlserver收到任何乙個指令,包括查詢(query)、批處理(batch)、儲存過程、觸發器(trigger)
、預編譯指令(prepared statement)和動態sql語句(dynamic sql statement)要完成語法解釋、語句解釋,
然後再進行「編譯(compile)」,生成能夠執行的「執行計畫(execution plan)」。在編譯的過程中,
sqlserver會根據所涉及的物件的架構(schema)、統計資訊以及指令的具體內容,估算
可能的執行計畫,
以及他們的成本(cost),最後選擇乙個sqlserver認為成本最低的執行計畫來執行。
執行計畫生成之後,
sqlserver通常會把他們快取在記憶體裡,術語統稱他們叫「plan cache」以後同樣的語句執行,sqlserver就可以使用同樣的執行計畫,而無須再做一次編譯。
這種行為叫「重用(reuse)或者叫重用執行計畫」。但是有時候,哪怕是一模一樣的語句,sql下次執行還是要再做一次編譯。
這種行為叫「重編譯(recompile)」。
執行計畫的編譯和重編譯都是要消耗資源的。
如果執行計畫能夠重用,那麼sqlserver就不需要再執行上面的過程,加快執行指令的速度,很多語句調優的文章裡提到資料庫重用執行計畫就是指這個意思
執行計畫重用的利弊
執行計畫的好壞當然決定了語句最終的執行速度。對於同樣的一條語句,使用好的執行計畫可能會比差的要快幾百倍,甚至上千倍。
所以從這乙個角度來講,每執行一條語句,都把他先編譯一遍當然是最好的。他能夠保證使用的執行計畫是sqlserver能找到的最優的。
但是sqlserver每秒鐘可能會執行成百上千的指令。如果每個都編譯一遍,是資源的一種浪費。所以sqlserver在這裡也試圖尋找乙個平衡點,
使用有限的compile/recompile,得到最好的整體效能
執行下面的指令,就能夠看到sqlserver當前快取的執行計畫有哪些(請別在生產伺服器上直接執行因為上面往往有龐大的快取)
1select
*from sys.[
syscacheobjects
]
重編譯的發生場景
但是有些時候,sqlserver為了確保返回正確的值,或者有效能上的顧慮,有意不重用快取在記憶體裡的執行計畫,而現場編譯乙份。
這種行為,被稱為重編譯(recompile)。下面是比較常見的會發生重編譯的情形:
1、當指令或者批處理所涉及的任何乙個物件(**或者檢視)發生了架構(schema)變化
例如,在表或者檢視上新增或刪除了乙個字段,新增或者刪除了乙個索引,在表上新增或者刪除了乙個約束條件(constraints)等。
定義發生了變化,原來的執行計畫就不一定正確了,當然要重編譯
2、執行過sp_recompile
當使用者在某個儲存過程或者觸發器上執行過sp_recompile後,下一次執行他們就會發生一次重編譯。
如果使用者在某個表或者檢視上執行了sp_recompile,那麼所有引用到這張表(或者檢視)的儲存過程在下一次執行前,都要做重編譯
3、有些動作會清除記憶體裡的所有執行計畫,迫使大家都要做重編譯
例如,下列動作會清除整個sqlserver伺服器快取的所有執行計畫:
(1)detach乙個資料庫
(2)對資料庫做了公升級,在新的伺服器上,會發生執行計畫清空
(3)執行了dbcc freeproccache
(4)執行了reconfigure語句
(5)執行了alter database..collate語句修改了某個資料庫的字符集(collation)
下列動作會清除sqlserver伺服器快取的某個資料庫的執行計畫:
dbcc flushprocindb
清除sql server 2000伺服器記憶體中的某個資料庫的儲存過程快取內容
1declare
@aint
2select@a=
db_id('
gposdb')
3dbcc flushprocindb(@a)
alter database ...modify name語句
alter database ...set online語句
alter database...set offline語句
alter database...set emergency語句
drop database 語句
當乙個資料庫自動關閉時
dbcc checkdb語句結束時
4、當下面這些set 開關值變化後,先前的那些執行計畫都不能重用
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
這是因為這些set開關會影響語句的執行的行為,甚至帶來不同的結果。他們發生變化了,sqlserver就要根據新的設定重做執行計畫
5、當**或者檢視上的統計資訊發生變化後
當統計資訊被手動更新後,或者sqlserver發現某個統計資訊需要自動更新時,sqlserver會對所涉及的語句都做重編譯
需要說明的是,在sqlserver裡,執行計畫重用並不一定是一件好事,而編譯/重編譯也不一定是一件壞事。
計畫重用可以幫助sqlserver節省編譯時間,對降低cpu使用率和減少阻塞都有好處,但是缺點是每次重用的計畫並不一定是最合適的計畫。
引數嗅探parameter sniffing就是典型的計畫重用帶來的負效應。編譯和重編譯當然能給當前執行的語句帶來盡可能準確執行計畫,
但是對於經常執行的語句,尤其是一些執行速度比較快的語句,可能其編譯時間佔最後總時間的相當大比例。這對資源來講是乙個很大的浪費
一般來說,sqlserver能夠很好地在編譯與重編譯之間做平衡,大部分情況下沒什麼問題的。
SQLSERVER編譯與重編譯
編譯的含義 當sqlserver收到任何乙個指令,包括查詢 query 批處理 batch 儲存過程 觸發器 trigger 預編譯指令 prepared statement 和動態sql語句 dynamic sql statement 要完成語法解釋 語句解釋,然後再進行 編譯 compile 生...
sql server 編譯與重編譯詳解
sqlserver編譯與重編譯 編譯的含義 當sqlserver收到任何乙個指令,包括查詢 query 批處理 batch 儲存過程 觸發器 trigger 預編譯指令 prepared statement 和動態sql語句 dynamic sql statement 要完成語法解釋 語句解釋,然後...
sql編譯與重編譯
sql 編譯與重編譯 1.sp recompile 使儲存過程和觸發器在下次執行時重新編譯。2.sp refreshview 如果檢視所依賴的基礎物件發生更改 如 表增加了乙個字段 則檢視不會自動更新,這時需要呼叫該儲存過程來對檢視進行重新整理。有人說,重新開啟一下檢視就可以更新檢視,但我試了沒有成...