程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> SqlServer數據庫 >> 關於SqlServer >> SQL Server使用游標處理Tempdb究極競爭-DBA問題-程序員必知

SQL Server使用游標處理Tempdb究極競爭-DBA問題-程序員必知

編輯:關於SqlServer

SQL Server tempdb分配競爭算是DBA老生常談的問題了,幾乎現在所有的DBA都知道多建幾個文件來解決/緩解問題.但是深層次的的競爭依舊不可避免.這裡給大家剖析下游標在tempdb中的特點使其在一定場景下替代臨時表/表變量對象,解決深層次的tempdb競爭問題.

在拋出這個不可避免的問題之前我們先簡要看下什麼是tempdb競爭.

我們拿SQL Server創建一個臨時表的過程來描述

1 在系統表中創建表的條目(系統數據頁中)

2 分配一個IAM頁並找到一個混合區在PFS頁中標記

3 分配一個數據頁(查看SGAM頁,查看PFS頁後並更新,更新IAM頁)

4 表記錄記錄到系統表中

從上述過程可以看出創建一個簡單臨時表需要查找,更新一系列的系統表/系統數據頁,且當使用完刪除臨時表時上述操作逆向進行.索引相應的創建/銷毀一旦大量並發,內部競爭也就產生了.雖然tempdb的緩存策略一定程度可以緩解相應創建過程的IAM,數據頁分配, Sql Server tempdb原理-緩存機制解析實踐,但競爭依舊.

可以看到SGAM,PFS等系統頁是表創建過程的必經之路,他的分配競爭也就十分明顯了.這也就是為什麼采用多個數據文件,讓系統頁(包含系統表)在分散在多個數據文件中的以減輕分配競爭的壓力原因.

到此也許大家都改猜到了終極問題是什麼了,就是對系統對象的操作.連SQL Server大牛Paul Randal都為之頭疼的問題.

具體哪些對象呢,我們可以簡單測試捕捉下如圖1-1

使用SQLQUERYSTRESS捕捉

Code

create table #t
(id int,
str1 varchar(10)
)
---SSMS中開啟會話捕捉
SELECT resource_description,* FROM SYS.dm_os_waiting_tasks
WHERE session_id>50


                                                     圖1-1

可以看到圖中tempdb中系統頁 2:1:53中發生典型的Pagelatch競爭.我們用dbcc page來看下頁的情況如圖2-2

Code

dbcc traceon(3604)
go
dbcc page(2,1,53,1)
select OBJECT_NAME(7)----the object_id from dbcc page

                                              圖2-2

可以看到在系統對象sysallocunits處發生了競爭,當然還有許多其他的系統對象,感興趣的朋友自行捕捉.

大量的針對系統對象表的操作使得tempdb其吞吐難以得到進一步的提升,這個是由系統本身的運作方式引發的,當然面對如此巨量的tempdb使用,就沒有別的方式了嗎?這時我不能給肯定的答案,但可以給大家一個IT界的流行答案:It depends :)

在介紹游標前,先簡單說下面對tempdb競爭中針對系統表競爭的常規處理方式

1 減小針對系統對象的事務大小(如select * into #的使用)

2 減小tempdb的使用頻次(看似廢話,但實際中的確可能用不到這麼多)

3 臨時對象中少使用約束造成額外的系統對象負擔.

好了接下來該說游標了,貌似八竿子打不著的事兒,實際上的確如此,我們只是利用游標的特性在極其特殊的場景下來解決相應問題.

也許你已經猜到了,游標是使用tempdb的,歸類到worktables中,使用worktables的對象如游標,dbcc checkdb,merge join,exchange spill等等.worktables是tempdb中一種普遍而又特殊的使用方式,他只在SQL Server內部中應用,給它定義為”temporary rowsets”,他的object id是負的,且無需系統表的記錄!

我們來簡單驗證說明下

code

use tempdb
checkpoint ---生產環境中慎用
dbcc checkdb(master) –這裡采用dbcc checkdb探究worktables
select Description,* from fn_dblog(null,null)

得到的tempdb Log如圖 2-1


                                                 圖2-1

我們用dbcc page分析此頁 可以看到這個是個IAM頁如圖2-2

code

dbcc traceon(3604)
dbcc page(2,4,104,3)


                                                   圖2-2

我們進而分析IAM分配的數據頁,發現他就是一個簡單的數據頁,不屬於任何系統對象如圖2-3

Code

dbcc traceon(3604)
dbcc page(2,5,104,3)


                                           圖2-3

OK,至此聯想起游標同樣適用worktables,我們可能聯想到了一些游標適用的場景居然還可以幫助tempdb緩解競爭.至於何種場景?It depends,大家自己去聯想吧,但tempdb遇到相應競爭時我是否可以采用?朋友們自己抉擇吧.

最後看圖說話如圖2-4

Code

--cursor
declare @cur cursor 
set @cur =cursor For select * from tt
--temp table
create table #tt (id int)
insert into #tt select * from tt

 

                                                    圖2-4

以上敘述是否改變了你對游標的看法呢?程序員朋友們,當DBA告訴你使用tempdb太多時是否考慮換種方式使用tempdb, DBA朋友們,不要輕易告訴程序員們過度使用tempdb.

結語 任何系統的愉快運轉都是基於某種狀態的平衡.我們需要在復雜環境中的性能瓶頸,資源消耗,相應時間等等因素中找到平衡點.什麼樣的平衡點? It depends :)

ps:sql server 數據庫 ' ' 附近有語法錯誤

昨天做項目時候,遇到標題的問題,代碼跟蹤把sql 語句 復制出來在數據庫執行不了,然後重新寫個一模一樣的,然後在 賦值到代碼中,還是同樣的錯誤,就是不知道哪裡出現了錯誤,最後 把 sql 語句寫成最簡單的 select * from tab  還是同樣的錯誤。

然後 ,然後就不會了。

最後在這個語句寫同樣的語句,最後發現問題了,新寫的sql 語句的 select 變 顏色了,而之前的賦值出來的  select 和 字段 表名的顏色一樣,證明系統 不承認它是關鍵字,把這個select 刪掉在 這個位置上重新寫,還是同樣的錯誤,最後發現原來在 這個select 前面有個全角的 空格,全角空格真的是用肉眼看不出來啊,恍然大悟,才知道  '   '    附近有語法錯誤 ,意思是  空格  有語法錯誤,證明不是 sql server 支持的 空格格式。

這個問題百度了,也沒解決,希望 可以幫到其他人,又不是特別難的東西,但是找到問題還是很浪費時間。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved