以文本方式查看主題 - 安易免費財務軟件交流論壇 (http://m.gangyx.cn/bbs/index.asp) -- 電腦知識交流 (http://m.gangyx.cn/bbs/list.asp?boardid=11) ---- SQL Server2008存儲結構之堆表、行溢出(四) (http://m.gangyx.cn/bbs/dispbbs.asp?boardid=11&id=32404) |
|||||||||||||||||||||||||||||||||||||||||||||
-- 作者:炙天 -- 發布時間:2011/1/13 8:49:28 -- SQL Server2008存儲結構之堆表、行溢出(四) 下面讓我們將該記錄的describle字段更新為非空值后,再看看該記錄存儲結構相應的變化。 UPDATE testheap SET describle=\'abc\' WHERE id=1 再次使用dbcc page(testdb,1,224,1)命令
我們不難發現狀態A,狀態B,定長長度、定長內容和字段總數是沒有發生任何變化的。 NULL位圖部分變成了e0即11100000,表示describle字段即第五個字段不為空了 第一個和第二個變長列數據終止位置分別加了2個長度,這是因為當第三個變長列變更為非空后,自動添加了2個字節的第三個字段的維護字段 第一個變長列數據終止位置從7a00變更為7c00 第二個變長列數據終止位置從7b00變更為7d00 新增加的第三個變長列終止位置為8000 同時在第一、二列變長列的數據后面新增加了616263,即字符串”abc” 還有一個最顯著的區別就是該記錄的偏移位置顯然轉到了尾部,即5F1E的位置;但很奇怪的是該記錄原來的位置上還保留著原值,并沒有刪除掉。也就是說對于該記錄而言,應該是先刪除,然后又添加了一條新紀錄,只是把指針指向了新的偏移地址而已。 最后觀察一下記錄是如何刪除的 DELETE FROM testheap WHERE ID IN (2,3) 當我們對比一下刪除前后兩條記錄的信息,發現基本上原來的位置上數據沒有發生任何變化,只是原來的slot1和slot2已經不存在了。即SQL Server認為該數據已經不存在了。
行溢出頁面 USE TESTDBCREATE TABLE testOverFlow ( ID INT IDENTITY(1,1), NAME1 VARCHAR(5000), NAME2 VARCHAR(5000) ) INSERT INTO testOverFlow (NAME1,NAME2) SELECT REPLICATE(\'A\',5000),REPLICATE(\'AB\',2500) UNION SELECT REPLICATE(\'B\',5000),REPLICATE(\'BA\',2500) SELECT * FROM testOverFlow SELECT type_desc total_pages,used_pages,data_pages, testdb.dbo.f_get_page(first_page) first_page_address, testdb.dbo.f_get_page(root_page) root_address, testdb.dbo.f_get_page(first_iam_page) IAM_address FROM sys.system_internals_allocation_units WHERE container_id IN (SELECT partition_id FROM sys.partitions WHERE object_id in (SELECT object_id FROM sys.objects WHERE name IN (\'testoverflow\'))) DBCC TRACEON(3604) DBCC PAGE(testdb,1,54242,2) --行內數據 DBCC PAGE(testdb,1,52343,2) --行遷移數據 --同時我們也可以通過dbcc ind獲取所有數據頁面地址,然后進行頁面信息顯示 TRUNCATE TABLE tablepage; INSERT INTO tablepage EXEC (\'DBCC IND(testdb,testOverFlow,1)\'); SELECT PagePID,IAMPID,ObjectID,IndexID,Pagetype,IndexLevel, NextPagePID,PrevPagePID FROM tablepage 在NAME2字段之前和普通的行記錄信息是一致的,我們只從NAME2字段開始就可以了。NAME2字段在NAME1字段之后,保存了以下內容,即改列的溢出列類型、節點類型、數據庫更新次數、字段長度、指向OVERFLOW頁的指針。
LOB頁面 從SQL Server 2005版本以后中,新增加了大值數據類型varchar(max)、nvarchar(max)、varbinary(max)。大值數據類型最多可以存儲2^30-1個字節的數據。 從行為上來講這幾個數據類型和之前的數據類型 varchar、nvarchar 和 varbinary 相同。 按照微軟的說法是用這個數據類型來代替之前的text、ntext 和 image 數據類型,它們之間的對應關系為: varchar(max)-------text; nvarchar(max)-----ntext; varbinary(max)----image 對大值數據類型的操作更類似于之前的varchar和varbinary之后,因此用法上也比之前的text和image比靈活和便宜。同時觸發器也可以直接引用大值數據類型;而之前的text和image是不行的。 因此varchar(max)與varchar(n)和text有著千絲萬縷的聯系。對于varbinary(max)也一樣。 因為之前我們已經觀察過varchar(n)的行為,那么讓我們看看這個新的varchar(max)與varchar(n)、text到底有什么不同。 CREATE TABLE testVARCHARMAX 運行結果如下:
我們很容易發現兩者的共同之處,就是兩個表都包括LOB_DATA數據類型的分配單元,但是testVARCHARMAX表的LOB_DATA并沒有分 配頁面,而testTEXT表卻分配了3個頁面;同時testVARCHARMAX表比testTEXT表多了一個數據頁面,這是怎么回事呢? 讓我們首先看看testVARCHARMAX表的第217個數據頁面
讓我們通過Internals Viewer插件看一下對該記錄的解讀
與之前的堆表的介紹相比,基本上我們可以看到與varchar(n)的存儲結構式完全一致的,在此就不多做敘述了。 那么testTEXT表為什么會使用到LOB類型頁面呢?我們使用dbcc page命令查看一下。 運行dbcc page(testDB,1,222),我們從第96個字節開始閱讀。
從這個角度,我們看到222頁面類似于前面所講到的行溢出頁面,即在222頁面保留了一個指向行溢出頁面的指針 運行dbcc page(testDB,1,220,2),我們從第96個字節開始閱讀。
實際上我們從name字段內容之后閱讀就可以了,即0000d1 07000000 00dc0000 00010001 00
是不是有點像縮略版的行溢出信息? 既然有行溢出指針,必然有行溢出頁面,那我們再看看行溢出頁面的數據頁,即220頁面。實際上我們用dbcc page(testdb,1,220,3)閱讀該頁的信息更簡明一些。
很明顯slot 0記錄了第一條記錄remark字段的長度、數據類型和內容。 Slot 1,slot 2分別為兩個指針,記錄了remark字段的偏移地址和相應的文件號、頁面和槽號 這個與之前的行溢出頁面是有所不同的。 |