Sql Server tempdb原理-緩存機制解析實踐

Sql Server tempdb原理-緩存機制解析實踐

Tempdb就像Sqlserver的臨時倉庫,各式各樣的對象,數據在裏面進行頻繁計算,操作.大量的操作使得tempdb可能面臨很大壓力,tempdb中緩存的設計就是爲了緩解這些壓力.這次就爲大家介紹下tempdb的緩存機制.

 

在介紹緩存機制前,先簡單瞭解一下TempDB對象

一般我們把tempdb對象分爲兩種類型用戶對象和內部對象.用戶對象指通過顯式T-sql來創造的對象(如臨時表),內部對象指通過隱式T-sql創建的對象(Worktables)

注:在引入版本控制後,也可以此單獨分類(DMV sys.dm_db_file_space_usage中單獨列出)

用戶對象

臨時表

表變量(包含表值函數返回值及表值參數)

臨時存儲過程

用戶自定義對象

用戶在線(Online)創建索引空間

內部對象

Sorts(排序溢出)

Worktables(checkdb,遊標,Merge joins,假脫機,並行查詢交換溢出,LOB對象等)

Workfiles(hash join 溢出)

Version store(版本行控制)

查看對象使用情況

當tempdb數據文件很大或者有異常時,我們可以查看相應的使用情況.如何查看,沄劍的Blog如何查看某個查詢用了多少TempDB空間有詳細腳本.

Tempdb緩存機制

Tempdb中的衆多對象緩存機制不盡相同,其中一些操作(如Sort)採用內部的機制,對用戶是不可控的,這裏我們主要介紹常用對象臨時表/表變量(也是經常引發問題)的緩存機制.

臨時表緩存機制(#t)

只有使用存儲過程,觸發器,Functions才能緩存

以plan cache的形式緩存一個IAM頁和一個DatePage頁

禁止Create後使用DDL操作

禁止命名約束

可以看出臨時表的緩存是以proc執行計劃緩存的形式實現的.所以batch,動態sql是無法緩存的.值得注意的是既然是執行計劃緩存,我們就不能在proc中加WITH RECOMPILE關鍵字.

注意:緩存對象時局部臨時表,不包括全局臨時表.

我們通過一個簡單的實例來分析下緩存實現.

首先我們來看下一般batch的操作(非緩存)執行兩次,觀察日誌情況如圖1-1

batch create code

複製代碼
use tempdb
go
checkpoint
go
create table #t
(
id int
)
insert into #t select 1
drop table #t
select Operation,CONTEXT,[Transaction ID],AllocUnitId,AllocUnitName,[Page ID],[Transaction Name],Description from fn_dblog(null,null)
複製代碼

 

                                                                                 圖1-1

實際上我們可以看出第一次和第二次執行的日誌記錄情況是相同的.

再來看下proc方式

proc code

複製代碼
use tempdb
go
checkpoint
go

create proc p_tstcache
as
create table #t
(
id int
)
insert into #t select 1

exec p_tstcache------第一次執行後觀察日誌記錄如圖1-2

select Operation,CONTEXT,[Transaction ID],AllocUnitId,AllocUnitName,[Page ID],[Transaction Name],Description from fn_dblog(null,null)

checkpoint
go
exec p_tstcache------第二次執行後觀察日誌記錄信息如圖1-3

select Operation,CONTEXT,[Transaction ID],AllocUnitId,AllocUnitName,[Page ID],[Transaction Name],Description from fn_dblog(null,null)
複製代碼

 

 

                                            圖1-2

 

                                                圖1-3

 

 

可以看到當存儲過程第二次執行時使用了緩存,日誌記錄數明顯減少.使用完成後繼續緩存。

緩存的益處

我們通過一個簡單的壓力測試來看下緩存的效果.

我們使用sqlquerystress開100的threads分別執行1000次看下batch,proc,proc中create後ddl的效果.(感興趣的朋友可以觀察相應的計數器 temp tables creation rate) 圖1-4

注意:預先設定好tempdb數據日誌文件大小,避免因爲文件增長帶來的測試偏差.

Code 1 batch

create table #t
(id int)
Drop table #t

Code2 proc

Create proc p_tstcache
As
create table #t
(id int)

Code 3 proc ddl after create script

create proc p_tstcache_ddl
as
create table #t
(id int)
Create index ix_id on #t(id) ----ddl after create

 

                                                   圖1-4

 

可以看到因爲緩存機制,在一些應用頻繁創建臨時表的實例中我們可以通過proc中完成臨時表的構建從而緩解競爭.但應注意proc 臨時表cache的限制.

關於表變量.

表變量的緩存機制與臨時表相同(注: 表值參數不支持緩存)

表變量是不能創建索引的,但可以有個默認約束

表變量沒有統計信息

表變量不支持事務

關於Proc中顯式drop臨時表.

微軟聲稱proc中顯式drop臨時表並不受create後DDL的影響,但在現實生產環境中的情況,顯式drop還是有一定影響的.況且proc執行完成後字自動緩存處理,沒必要顯式drop.

關於臨時表/表變量緩存應用

通過上面的實例我們可以看到,如果要利用proc緩存cache是有不少限制的.現實生產環境中我們有可能使用到臨時表(表變量)需要創建索引以提高查詢效率.這時就需要我們來權衡.實際上高併發查詢中使用數據量較大的臨時表此時我們可以在創建臨時表的腳本中一併完成索引的創建.但高併發的大臨時表下的壓力會是創建過程嗎?

結語:有時候DBA的工作的確是手藝活,需要不停的打磨權衡.在業務穩定的情形下如果我們無法調整硬件環境,就需要我們打造業務所需的合理平衡.

Involuntary DBA
發佈了256 篇原創文章 · 獲贊 20 · 訪問量 83萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章