前文
本篇會跟大家對於SQL-Server
資料表深入淺出的介紹.
關於子頁層
資料會存在子頁層中(page),一個Page
大小為 8K/Page => 8092(8060 bytes)
每個Page除了存取資料還會存放一些
MetaData
,我們可以先當作是每個Page大小是8K
Heap資料表
如果一張資料表沒有Clustered Index
就會為Heap資料表,這意味著Heap
資料表的資料不會有排序一直把資料新增進資料表中,Heap
資料表Insert
資料快
適合使用在Log資料表、Event資料表、稽核資料表….一直新增資料但比較少查詢表
IAM(index allocation map)
當Heap資料表要搜尋資料SQL-Server
透過IAM(index allocation map)去尋要掃描Page範圍,因為IAM會以範圍存在於檔案中的順序來表示它們,這代表循序的堆積掃描都將依檔案順序進行。
使用IAM分頁設定掃描順序也表示堆積中的資料列通常不會依插入順序傳回
IAM Page在讀取資料的示意圖
可以看到讀取Page中資料順序和新增資料順序不一樣.
forwarding pointer
假如在Heap資料表更新欄位資料,就可能會造成forwarding pointer
製造forwarding pointer
是因為原本Page
塞不下更新後資料就會先把資料搬到另一個新建立Page
上並在原本Page
建立一個類似指標東西指向它.
這個指標會存在原本的Page大小是16 byte
forwarding pointer(Demo)
一個Page大小是8k
我們建立一個ForwardingPointers
資料表,並且新增3筆資料進去
其中有一筆資料
replicate('2',7800)
佔據78xxBytes.
1 | create table dbo.ForwardingPointers |
新增完後我們利用DMV
查詢目前ForwardingPointers
使用的Page數量可以看到只使用一頁
因為目前資料大小可以放在同一個Page
1 | select page_count, avg_record_size_in_bytes, avg_page_space_used_in_percent |
我們將dbo.ForwardingPointers
另外兩個Val IS NULL
更新成replicate('2',7800)
1 | UPDATE dbo.ForwardingPointers |
再查詢一次dbo.ForwardingPointers
使用Page,能發現已經使用了3個Page(因為已經觸發forwarding pointer
)
已經把這次更新的資料搬到新Page上,因為更新後的資料大小已經超過目前Page可以負擔的大小
RID Lookup
在資料庫索引深入淺出(一)有說,資料表沒有Clustered Index
且使用Index
所有查詢欄位不包含在Converting Index
中就會透過RID Lookup
查找確切Page上的Row(藉由Row-Id)
此資料表是
Heap
資料表在NonClustered Index
中會存放Heap RID
記得在
DBCC IND
取得的PID是要找PageType = 2
1 | DBCC traceon (3604); |
透過DBCC
可以看到查找資料表Page資料可以顯示如下結果集.
如果是Heap資料表會有一個欄位是Heap RID(Key)
欄位.
HEAP RID:0x40110F0001002900
大小 8 bytes
- FID(2 bytes)
- PID(4 bytes)
- SLOT(2 bytes)
可藉由下面的Script來拆解Heap RID(Key)
資料
1 | --轉換RID為 FID:PID:slot格式 |
透過上面Script我們可以得到1:987456:41
我們在透過
1 | DBCC PAGE(AdventureWorks2012_Data,1,987456,3) |
就可以查找到我們要的資料在PID = 987456
這個Page中.
dbcc page 語法
下面語法透過dbcc page
可以了解資料表存取資訊
1 | /* 建立測試資料表 */ |
PageType – the page type. Some common ones are:
- 1 – data page
- 2 – index page
- 3 and 4 – text pages
- 8 – GAM page
- 9 – SGAM page
- 10 – IAM page
- 11 – PFS page
1 | dbcc traceon (3604); |
- 第一個參數是數據庫名或數據庫ID。
- 第二個參數是數據庫中的對象名或對象ID,對象可以是表或者索引視圖。
- 第三個參數是一個非聚集索引ID或者 1, 0, 1, or 2. 值的含義:
- 0: 只顯示對象的in-row data頁和 in-row IAM 頁。
- 1: 顯示對象的全部頁, 包含IAM 頁, in-row數據頁, LOB 數據頁row-overflow 數據頁 . 如果請求的對象含有聚集所以則索引頁也包括。
- -1: 顯示全部IAM頁,數據頁, 索引頁 也包括 LOB 和row-overflow 數據頁。
- -2: 顯示全部IAM頁。
__此文作者__:Daniel Shih(石頭)
__此文地址__: https://isdaniel.github.io/dbtable/
__版權聲明__:本博客所有文章除特別聲明外,均採用 CC BY-NC-SA 3.0 TW 許可協議。轉載請註明出處!