佳木斯湛栽影视文化发展公司

主頁 > 知識庫 > SQL Server 2008存儲(chǔ)結(jié)構(gòu)之GAM、SGAM介紹

SQL Server 2008存儲(chǔ)結(jié)構(gòu)之GAM、SGAM介紹

熱門標(biāo)簽:呼叫中心市場需求 網(wǎng)站排名優(yōu)化 AI電銷 服務(wù)外包 地方門戶網(wǎng)站 Linux服務(wù)器 鐵路電話系統(tǒng) 百度競價(jià)排名
當(dāng)我們創(chuàng)建一個(gè)數(shù)據(jù)庫的時(shí)候,例如以缺省的方式CREATE DATABASE TESTDB,SQLServer自動(dòng)幫我們創(chuàng)建好如下兩個(gè)數(shù)據(jù)庫文件。

這兩個(gè)數(shù)據(jù)文件是實(shí)實(shí)在在的操作系統(tǒng)文件,其中一個(gè)是叫行數(shù)據(jù)文件,用來存儲(chǔ)數(shù)據(jù)庫的各種對象,另外一個(gè)是日志文件,從來記錄數(shù)據(jù)變化的過程。

  從邏輯角度而言,數(shù)據(jù)庫的最小存儲(chǔ)單位為頁即8kb。

  數(shù)據(jù)庫被分成若干邏輯頁面(每個(gè)頁面8KB),并且在每個(gè)文件中,所有頁面都被連續(xù)地從0到x編號,其中x是由文件的大小決定的。我們可以通過指定一個(gè)數(shù)據(jù)庫ID、一個(gè)文件ID、一個(gè)頁碼來引用任何一個(gè)數(shù)據(jù)頁。每個(gè)數(shù)據(jù)頁則用來存儲(chǔ)表和索引,以及相關(guān)的數(shù)據(jù)庫管理信息。

  我們順著上面數(shù)據(jù)文件的路徑可以找到該文件,觀察一下新建的數(shù)據(jù)文件的大小為:

  2.18 MB (2,293,760 字節(jié))=2,293,760b/8kb=280個(gè)頁面=35個(gè)區(qū)

  數(shù)據(jù)庫進(jìn)行空間管理的最小單位為區(qū)(extents)。

  一個(gè)區(qū)由8個(gè)邏輯上連續(xù)的頁面組成(64KB的空間)。為了能夠更有效地分配空間,SQL Server 2008不會(huì)為少量的數(shù)據(jù)向數(shù)據(jù)表分配整區(qū)的空間。SQL Server 2008有兩種類型的區(qū)。

  統(tǒng)一類型的區(qū) 這些區(qū)為單個(gè)對象所有,區(qū)中所有的8個(gè)數(shù)據(jù)頁只能被所屬對象使用。

  混合類型的區(qū) 這些區(qū)能為最多8個(gè)對象共享。

  SQL Server為新的表或索引從混合類型的區(qū)中分配頁面。當(dāng)該表或索引增長到8個(gè)頁面時(shí),以后所有的分配都使用統(tǒng)一類型的區(qū)。

  當(dāng)一張表或一個(gè)索引需要更多的空間時(shí),SQL Server需要找到能夠用來分配的空間。如果該表或索引整體仍然少于8個(gè)頁面,SQL Server必須找到能夠用來分配的混合類型區(qū)構(gòu)成的空間。如果表或索引有8個(gè)頁面或更大,SQL Server必須找到一個(gè)自由的統(tǒng)一類型的區(qū)。

  SQL Server使用兩種特殊類型的頁面來記錄哪些區(qū)已經(jīng)被分配出去了,哪些類型(混合類型或統(tǒng)一類型)的區(qū)可供使用:

  全局分配映射(Global Allocation Map,GAM)頁面 這些頁面記錄了哪些區(qū)已經(jīng)被分配并用作何種用途。一個(gè)GAM頁面在它所覆蓋空間里針對每一個(gè)區(qū)都有一個(gè)數(shù)據(jù)位。如果數(shù)據(jù)位為0,那么對應(yīng)的區(qū)正在使用;如果該數(shù)據(jù)位為1,那么該區(qū)為自由區(qū)。一個(gè)GAM頁面除了頁面頭部和其他一些需要記入的開銷大概有8 000字節(jié)或者說64 000位空間可用,所以每個(gè)GAM頁面可以覆蓋64 000個(gè)區(qū),也就是大約4GB的數(shù)據(jù)。這意味著一個(gè)文件的每4GB空間對應(yīng)一個(gè)GAM頁面。

  共享全局分配映射(Shared Global Allocation Map,SGAM)頁面 這些頁面記錄了哪些區(qū)當(dāng)前被用作混合類型的區(qū),并且這些區(qū)需含有至少一個(gè)未使用的頁面。就像一個(gè)GAM頁面,每一個(gè)SGAM頁面覆蓋了大約64 000個(gè)區(qū),也就是大約4GB的數(shù)據(jù)。一個(gè)SGAM頁面在它所覆蓋空間里針對每一個(gè)區(qū)都有一個(gè)數(shù)據(jù)位。如果數(shù)據(jù)位為1,那么對應(yīng)的被使用的區(qū)為混合類型,并且該區(qū)有一些自由頁面;如果數(shù)據(jù)位為0,那么對應(yīng)的區(qū)不是一個(gè)混合類型的區(qū),或者雖然是一個(gè)混合類型的區(qū),但是所有的頁面都已被使用了。

  表4-2顯示了基于每一個(gè)區(qū)當(dāng)前的使用情況,在GAM和SGAM中該區(qū)所對應(yīng)的比特位模式。
區(qū)的當(dāng)前使用情況 GAM比特位設(shè)置 SGAM比特位設(shè)置
自由,未使用 1 0
統(tǒng)一類型或已全部使用的混合區(qū) 0 0
含有自由頁面的混合區(qū) 0 1

  如果SQL Server需要找到一個(gè)新的完全沒有使用的區(qū),那么它可以使用任何一個(gè)在GAM頁面中對應(yīng)的比特位值為1的區(qū)。如果SQL Server需要找到一個(gè)有著可用空間(有一個(gè)或多個(gè)自由頁面)的混合類型的區(qū),那么它可以尋找一個(gè)對應(yīng)的GAM中的值為0、SGAM中的值為1的區(qū)。如果不存在有可用空間的混合類型的區(qū),SQL Server會(huì)使用GAM頁面來尋找一個(gè)全新的區(qū)并將其分配為混合類型的區(qū),然后使用該區(qū)中的一頁。如果根本沒有自由區(qū),那么這個(gè)文件已經(jīng)滿了。

第0頁 第1頁 第2頁 第3頁 第4頁 第5頁 第6頁 第7頁
m_type=15 m_type=11 m_type=8 m_type=9 m_type=0 m_type=0 m_type=16 m_type=17
頭文件頁 PFS頁 GAM頁 SGAM頁 保留頁 保留頁 DCM頁 BCM頁

  SQL Server能夠迅速地鎖定一個(gè)文件中的GAM頁面,因?yàn)樗偸俏挥谌魏螖?shù)據(jù)庫文件的第三頁上(頁碼為2)。SGAM頁面是在第四頁上(頁碼為3)。下一個(gè)GAM頁面出現(xiàn)在第一個(gè)GAM頁面(頁碼為2)以后的每511 230個(gè)頁面中,并且下一個(gè)SGAM頁面出現(xiàn)在第一個(gè)SGAM頁面(頁碼為3)以后的每511 230個(gè)頁面中。每一個(gè)數(shù)據(jù)庫文件的頁碼為0的頁面是文件頭頁面,并且每個(gè)文件僅有一頁。頁碼0是頭文件頁,頁碼1是頁面自由空間頁(Page Free Space,PFS)。

  在SQLServer2008的每一個(gè)數(shù)據(jù)庫中的前八頁順序都是固定的。

  除了第9頁為數(shù)據(jù)庫的BOOT頁以外,從第8頁到第173頁為SQLServer2008內(nèi)部系統(tǒng)表的相關(guān)存儲(chǔ)信息,然后從第174頁到第279頁為未分配頁面。因?yàn)榈谝豁搹?開始,所以剛好280頁,即和我們看到的數(shù)據(jù)庫數(shù)據(jù)文件的大小完全相等。

第8頁 第8頁 第8頁 第N頁 第173頁 第279頁
m_type=1 m_type=13 m_type in (1,2,10) N/A
Data頁 Boot頁 主要為內(nèi)部系統(tǒng)表相關(guān)信息 未分配

  以下截圖是通過SQLServer2008的Internals Viewer插件看到的整體頁面結(jié)構(gòu),該插件是從http://www.SQLInernalsViewer.com網(wǎng)站下載的,分為不同的.net版本。

  備注:TESTDB為新創(chuàng)建的空數(shù)據(jù)庫,沒有任何用戶自定義對象,直到有建表腳本為止;


關(guān)于數(shù)據(jù)庫頁類型如下所示:

類型 頁面類型名稱 頁面類型描述
1 Data page 堆表和聚集索引的葉子節(jié)點(diǎn)數(shù)據(jù)
2 Index page 聚集索引的非葉子節(jié)點(diǎn)和非聚集索引的所有索引記錄
3 Text mixed page A text page that holds small chunks of LOB values plus internal parts of text tree. These can be shared between LOB values in the same partition of an index or heap.
4 Text tree page A text page that holds large chunks of LOB values from a single column value.
7 Sort page 排序時(shí)所用到的臨時(shí)頁,排序中間操作存儲(chǔ)數(shù)據(jù)用的。
8 GAM page 全局分配映射(Global Allocation Map,GAM)頁面 這些頁面記錄了哪些區(qū)已經(jīng)被分配并用作何種用途。
9 SGAM page 共享全局分配映射(Shared Global Allocation Map,GAM)頁面 這些頁面記錄了哪些區(qū)當(dāng)前被用作混合類型的區(qū),并且這些區(qū)需含有至少一個(gè)未使用的頁面。
10 IAM page. 有關(guān)每個(gè)分配單元中表或索引所使用的區(qū)的信息
11 PFS page. 有關(guān)頁分配和頁的可用空間的信息
13 boot page. 記錄了關(guān)于數(shù)據(jù)庫的信息,僅存于每個(gè)數(shù)據(jù)庫的第9頁
15 file header page 記錄了關(guān)于數(shù)據(jù)庫文件的信息,存于每個(gè)數(shù)據(jù)庫文件的第0頁
16 DCM page 記錄自從上次全備以來的數(shù)據(jù)改變的頁面,以備差異備份
17 BCM page 有關(guān)每個(gè)分配單元中自最后一條 BACKUP LOG 語句之后的大容量操作所修改的區(qū)的信息


  實(shí)際上SQLServer還包括一些未公開的頁面類型,例如type 19,type 14等等。

  本章我們主要介紹GAM頁和SGAM頁,其他頁面類型會(huì)稍后介紹。

  那么如何查看頁面信息呢,從SQLServer2000起便開始提供了一個(gè)讀取數(shù)據(jù)頁結(jié)構(gòu)的命令DBCC Page。該命令為非文檔化的命令,具體如下:

  DBCC Page ({dbid|dbname},filenum,pagenum[,printopt])

  具體參數(shù)描述如下:

  dbid               包含頁面的數(shù)據(jù)庫ID

  dbname       包含頁面的數(shù)據(jù)庫的名稱

  filenum         包含頁面的文件編號

  pagenum      文件內(nèi)的頁面

  printopt            可選的輸出選項(xiàng);選用其中一個(gè)值:

                            0:默認(rèn)值,輸出緩沖區(qū)的標(biāo)題和頁面標(biāo)題

                           1:輸出緩沖區(qū)的標(biāo)題、頁面標(biāo)題(分別輸出每一行),以及行偏移量表

                           2:輸出緩沖區(qū)的標(biāo)題、頁面標(biāo)題(整體輸出頁面),以及行偏移量表

                           3:輸出緩沖區(qū)的標(biāo)題、頁面標(biāo)題(分別輸出每一行),以及行偏移量表;每一行后跟分別列出的它的列值

  如果要想看到這些輸出的結(jié)果,還需要設(shè)置DBCC TRACEON(3604)。

  如前文所述,GAM頁一定存在于該數(shù)據(jù)庫的第二個(gè)頁面,SGAM頁則一定存在于該數(shù)據(jù)庫的第三個(gè)頁面;而每一個(gè)數(shù)據(jù)庫都會(huì)存在文件編號為1的數(shù)據(jù)庫文件,所以我們執(zhí)行以下命令即可。

復(fù)制代碼 代碼如下:

DBCC TRACEON(3604)
DBCC PAGE(TESTDB,1,2,1) —查看GAM頁信息
DBCC PAGE(TESTDB,1,3,1) —查看SGAM頁信息
DBCC PAGE(TESTDB,1,2,2) —查看GAM頁信息和整體輸出頁面
DBCC PAGE(TESTDB,1,3,2) —查看SGAM頁信息和整體輸出頁面
DBCC PAGE(TESTDB,1,2,3) —查看GAM頁信息及相應(yīng)列值
DBCC PAGE(TESTDB,1,3,3) —查看SGAM頁信息及相應(yīng)列值
DBCC PAGE(TESTDB,1,2,1) WITH TABLERESULTS —以表格形式查看SGAM頁信息及相應(yīng)列值
DBCC PAGE(TESTDB,1,3,1) WITH TABLERESULTS —以表格形式查看SGAM頁信息及相應(yīng)列值

我們可以看到一個(gè)完整的頁面分為四個(gè)部分;BUFFER、PAGE HEADER、DATA和OFFSET TABLE。

  讓我們首先從GAM頁開始看起:

  BUFFER部分:

  顯示給定頁面的緩沖信息,是內(nèi)存中的結(jié)構(gòu),用于管理頁面,該信息僅當(dāng)該頁面處于內(nèi)存時(shí)才有意義。關(guān)于這個(gè)部分我們知之甚少,基本上無法找到相關(guān)材料。

BUF @0x03585CD8 每一次清空緩存再次查詢,地址都會(huì)改變
bpage = 0x060B4000 每一次清空緩存再次查詢,地址都會(huì)改變
bhash = 0x00000000 相對不變
bpageno = (1:2) 當(dāng)前頁面地址
bdbid = 8 sys.databases.database_id
breferences = 1 每一次清空緩存再次查詢,地址都會(huì)改變
bUse1 = 41490 每一次清空緩存再次查詢,地址都會(huì)改變
bstat = 0xc00009 相對不變
blog = 0x59ca2159 相對不變
bnext = 0x00000000 相對不變

  PAGE HEADER部分:
PAGE HEADER部分顯示的是該頁面上的所有報(bào)頭字段的數(shù)據(jù)

PAGE HEADER這部分內(nèi)容只有通過DBCC PAGE(TESTDB,1,2,2)即整體輸出頁面才能夠展現(xiàn);通過與上面表格的對照,我們勉強(qiáng)能識別一些相關(guān)存儲(chǔ)信息;當(dāng)這部分缺乏官方文檔的支持,為了避免無謂的猜測,所以暫時(shí)就不做深入探討了。

DATA 部分

DATA部分一般分為若干插槽號(Slot),如果是數(shù)據(jù)頁或索引頁的話,可以理解為一行記錄,SQLServer通過文件號+頁面號+插槽號用來唯一標(biāo)識表中的每一條記錄。但在GAM頁中我們可以把Slot 0理解為GAM頁的保留頁,共計(jì)94個(gè)字節(jié)。

  從第194個(gè)字節(jié)開始(頁面總是從第0個(gè)字節(jié)開始的),到第196個(gè)字節(jié),這三個(gè)字節(jié)代表已分配的分區(qū)的情況。即0000C0。

  我們再來看一下DBCC PAGE(TESTDB,1,2,3)的執(zhí)行結(jié)果。

上面顯示從第1頁到第168頁已分配,而第176頁到272頁未分配,和DBCC PAGE(TESTDB,1,2,2)顯示的194個(gè)頁面似乎有些矛盾,實(shí)際上是不矛盾的。如前文所述,GAM對未使用的分區(qū)標(biāo)識為0,而對已分配的分區(qū)標(biāo)識為1
  1個(gè)分區(qū)=64頁,因?yàn)榍?28個(gè)頁面均已分配,所以前兩個(gè)字節(jié)為00 00
  從第128個(gè)頁面起到第175個(gè)頁面也均已分配,實(shí)際上為6個(gè)區(qū)為0也就是說連續(xù)6個(gè)bit為0,一個(gè)字節(jié)為8個(gè)bit,最后兩個(gè)bit為11,所以該字節(jié)為0000 0011,在此需要反轉(zhuǎn)一下相關(guān)二進(jìn)制位;反轉(zhuǎn)之后為1100 0000即為C0。
  最后讓我們用Internals Viewer插件看一下GAM頁的全貌吧。



SGAM頁面

PAGE: (1:3)

BUFFER:
BUF @0x0358A7F4
bpage = 0x062AE000 bhash = 0x00000000 bpageno = (1:3)
bdbid = 8 breferences = 3 bUse1 = 14428
bstat = 0xc00009 blog = 0x21212159 bnext = 0x00000000

PAGE HEADER:
Page @0x062AE000
m_pageId = (1:3) m_headerVersion = 1 m_type = 9
m_typeFlagBits = 0x0 m_level = 0 m_flagBits = 0x200
m_objId (AllocUnitId.idObj)=99 m_indexId (AllocUnitId.idInd)=0 Metadata: AllocUnitId=6488064
Metadata: PartitionId = 0 Metadata: IndexId = 0 Metadata: ObjectId = 99
m_prevPage = (0:0) m_nextPage = (0:0) pminlen = 90
m_slotCnt = 2 m_freeCnt = 6 m_freeData = 8182
m_reservedCnt = 0 m_lsn = (18:435:5) m_xactReserved = 0
m_xdesId = (0:0) m_ghostRecCnt = 0 m_tornBits = 177043542
Allocation Status
GAM (1:2)=ALLOCATED SGAM (1:3)=NOT ALLOCATED PFS(1:1)=0x44 ALLOCATED 100_PCT_FULL
DIFF (1:6) = CHANGED ML (1:7) = NOT MIN_LOGGED

DATA:
Slot 0, Offset 0x60, Length 94, DumpStyle BYTE
Record Type = PRIMARY_RECORD Record Attributes =
Memory Dump @0x4F32C060
00000000: 00005e00 00000000 00000000 00000000 ?..^.............
00000010: 00000000 00000000 00000000 00000000 ?................
00000020: 00000000 00000000 00000000 00000000 ?................
00000030: 00000000 00000000 00000000 00000000 ?................
00000040: 00000000 00000000 00000000 00000000 ?................
00000050: 00000000 00000000 00000000 0000??????..............

Slot 1, Offset 0xbe, Length 7992, DumpStyle BYTE
Record Type = PRIMARY_RECORD Record Attributes =
Memory Dump @0x4F32C0BE
00000000: 0000381f 20ee2000 00000000 00000000 ?..8. . .........
00000010: 00000000 00000000 00000000 00000000 ?................
00001F30: 00000000 00000000 ???????????????????........

  以下為DBCC PAGE(TESTDB,1,3,3)得到的相關(guān)信息,有興趣的可以和20ee20做一下對比。

(1:0) - (1:32) = NOT ALLOCATED
(1:40) - = ALLOCATED
(1:48) - (1:64) = NOT ALLOCATED
(1:72) - (1:88) = ALLOCATED
(1:96) - = NOT ALLOCATED
(1:104) - (1:120) = ALLOCATED
(1:128) - (1:160) = NOT ALLOCATED
(1:168) - = ALLOCATED
(1:176) - (1:272) = NOT ALLOCATED

  最后讓我們用Internals Viewer插件看一下SGAM頁的全貌吧。



總結(jié)一下,關(guān)于GAM和SGAM頁比較困難的地方:

  1、 關(guān)于GAM和SGAM頁中的BUFFER信息基本無法理解,也找不到相關(guān)材料。

  2、 PAGE HEADER的部分信息和Slot 0中的一部分信息,也無法找到相關(guān)材料。

  3、 SGAM頁中的NOT ALLOCATED實(shí)際上是統(tǒng)一類型區(qū)或者已使用完的混合類型的區(qū),而ALLOCATED實(shí)際上為含有自由頁面的混合區(qū)。

  4、 GAM頁中0代表已分配,1代表自由區(qū);和一般的標(biāo)志位的含義剛好相反。

  5、 GAM和SGAM實(shí)際上只分配了280個(gè)頁面,即35個(gè)區(qū);顯示出來的數(shù)據(jù)內(nèi)容雖然很多,但后面的分區(qū)信息實(shí)際上是不存在的。

  6、 GAM和SGAM通過DBCC的printopt為3的屬性顯示出來的頁面分配信息看似是斷號的。

  7、 GAM和SGAM的區(qū)信息的字節(jié)是通過二級制反轉(zhuǎn)得到的。

  GAM和SGAM頁的總的大小為8192個(gè)字節(jié);文件頭為96個(gè)字節(jié),slot 0為94個(gè)字節(jié),slot 1的頭部的系統(tǒng)信息為4個(gè)字節(jié),尾部的系統(tǒng)信息為10個(gè)字節(jié),所以有效存儲(chǔ)應(yīng)為7988個(gè)字節(jié),63904個(gè)區(qū),511230個(gè)頁;事實(shí)上當(dāng)數(shù)據(jù)文件超過約4G的時(shí)候,我們將能在第511232頁、 第511233頁分別找到其對應(yīng)的GAM、SGAM頁面。

標(biāo)簽:湖南 崇左 衡水 仙桃 黃山 湘潭 銅川 蘭州

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《SQL Server 2008存儲(chǔ)結(jié)構(gòu)之GAM、SGAM介紹》,本文關(guān)鍵詞  ;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 收縮
    • 微信客服
    • 微信二維碼
    • 電話咨詢

    • 400-1100-266
    长顺县| 四子王旗| 太康县| 静海县| 霍林郭勒市| 平顶山市| 福鼎市| 延庆县| 惠水县| 砀山县| 舒城县| 丰宁| 荥阳市| 太原市| 芦溪县| 汉源县| 南宫市| 新兴县| 台南县| 大名县| 衢州市| 民权县| 珠海市| 炉霍县| 略阳县| 聂荣县| 黄平县| 福泉市| 宁化县| 京山县| 青冈县| 台安县| 边坝县| 烟台市| 鄂伦春自治旗| 法库县| 萨嘎县| 镇宁| 大名县| 太湖县| 松江区|