SQLSERVER的資料頁面結構

2022-01-11 21:35:36 字數 3257 閱讀 9088

在論壇裡經常有人問到sqlserver是怎麼存放基礎表資料的,既然不想查msdn,本人就在這裡說一下吧

基礎表資料都存放在資料頁裡面,sqlserver儲存資料都是按照「頁」為單位來存放在磁碟的,sqlserver從

磁碟讀寫資料也是按照 「頁」 為單位 一頁一頁地讀取到記憶體,所以有時候如果資料不能塞滿整個資料頁,那麼

這種情況就叫做:page split 頁拆分 或者 「碎片」(詳細的在文章結尾會跟大家解釋一下因為要先了解sqlservr

的資料頁面結構才能解釋清楚) ,sqlserver有時候需要讀取兩頁才能把使用者需要找的資料讀出來

,如果表加了索引的話可以通過重建索引的方法解決,沒有建立索引的話就沒有辦法了

因為建立了索引的表,表裡面的資料是放在b樹資料結構的索引頁,而不是堆資料結構的資料頁

好像說太多了,現在說一下資料頁面是怎樣存放資料:

每一行資料在資料頁面裡是怎麼存放的?

結構組成:每個sqlserver的資料頁面大致分成3個部分:頁頭,頁尾偏移量,資料儲存 這3個部分

假設現在有乙個表,表的結構是:

create table test(

a int,

b int

) 他在1:100這個頁面上儲存資料(1是資料庫的資料檔案id 亦即是fileid,100 是pageid 頁面編號)。

這個頁面結構大致如下圖

在頁頭部分,會記錄頁面屬性,包括頁面編號等,還會記錄當前頁面空閒部分的起始位置在**

這樣sqlserver在要插入新資料的時候,就能夠很快地找到開始插入的位置,而頁尾的偏移量

記錄了每一條資料行的起始位置。這樣sqlserver在找每一條記錄的時候,就能很快找到不會

把前一條記錄和後一條搞混。在圖例這一頁裡現在有兩條記錄:(1,100)和(2,200)第一條

記錄的開始位置是96,第二條記錄的開始位置是111,從126開始,是空閒的空間

當頁面裡的資料行發生變化的時候,sqlserver不但要去修改資料本身,還要修改這些偏移量的值,

以保證sqlserver能夠繼續準確地管理資料頁面裡的每一行

不知道大家明白不? 該睡覺了,加完班很睏哦

2012-12-21補充:

開頭說了碎片頁拆分,如果有索引的話也叫「索引碎片」,那麼這些碎片是怎麼造成的 以及如何避免和修復呢?

造成的原因很簡單:當你刪除表裡一條記錄的時候,sqlserver會去找這條記錄的所在頁面

然後刪除,當你刪除了之後,那麼那個資料頁面存放的資料就變成不連續的了,這時候就稱為「資料碎片」

就是頁面存放的資料不連續,當你刪除多條記錄,而這些記錄都在同乙個頁面,那麼就會造成資料塞不滿

整個頁面,當你插入一條記錄的時候,這條記錄是不會插入到你上次刪除的那條記錄的地方的,如果sqlserver

的最後乙個資料頁面(這些資料頁面是用雙向鍊錶來鏈結的)有位置就插入去,沒有位置就新開乙個頁面,然後插入

記錄如果存在這些碎片主要兩個弊端:

弊端一:sqlserver在查詢記錄的時候要查詢多個頁面才能找到那條記錄(特別使用表掃瞄執行計畫),sqlserver按一定順序

一條一條記錄地去找,這樣的話本來只需要讀取乙個頁面到記憶體,sqlserver現在需要讀取兩個頁面到記憶體(特別sqlserver

使用表掃瞄執行計畫的時候),會造成

記憶體的使用增大,查詢時間增多

弊端二:本來使用乙個頁面可以存放下連續的資料,現在需要兩個頁面才能存放下這些資料,造成磁碟空間的浪費,占用額外的

磁碟空間

如何避免和修復:

最好在表上建立乙個聚集索引,然後通過重建索引或者重新組織索引的方式使資料重新按照建立索引的那個欄位的順序重新排序

儲存,重建索引會把這些資料頁面重新排序把沒有「塞滿資料」的頁面重新「塞滿」,並有序排列(更詳細的大家可以看一下msdn)

看一下這些資料是如何按聚集索引的方式來有序存放的

msdn:聚集索引除了可以提高查詢效能之外,還可以按需重新生成或重新組織來控制表碎片。

也可以對檢視建立聚集索引。

聚集索引基於資料行的鍵值在表內排序和儲存這些資料行。每個表只能有乙個聚集索引,因為資料行本身只能按乙個順序儲存

只能按乙個順序儲存是指:當你建立聚集索引或者主鍵的時候,你有可能在多個列上建立了聚集索引或者復合主鍵

sqlserver只會按照你建立索引的時候的最左一列的字段來排序,只是一列,不是說先按第一列排序,

再按第二列排序,再按第三列排序。。。。。。

這個有很多人會混淆!!!!!!!!!!!!!!!

如果**上沒有聚集索引那麼這個問題不能解決,沒有聚集索引的表都是堆資料結構的表,就是說資料本身就沒有乙個排列方式

除非加乙個聚集索引,使資料有序排列,非聚集索引也不能解決因為非聚集索引只是在表上加了索引但是資料還是按照「堆」

資料結構來排列的,因為sqlserver的頁面型別有索引頁面,資料頁面,lob頁面,行溢位頁面,具體大家可以看一下

我之前寫的這篇

文章:sqlserver的**儲存組織結構

聚集索引設計指南

建立聚集索引

建立非聚集索引

非聚集索引設計指南

所以很多書上面都說乙個資料量比較大的表最好建立乙個聚集索引其實也是有道理的

2013-8-17 補充:

在正常的資料頁上,資料行緊接著頁的標頭按順序放置。頁的末尾是行偏移量表,對於頁中的每一行,每個行偏移表都包含乙個條目。

每個條目記錄對應行的第乙個位元組與頁首的距離。行偏移表中的條目與頁中行的順序相反

clickhouse insert的資料結構

clickhouse insert大致分為兩部分 1.sql語句部分 insert into table f1,f2 2.資料部分資料部分又分為3部分 頭,資料,尾 資料頭 資料塊1 資料塊2 資料塊n 資料尾從中可以看出 每個insert可以包含多個資料塊,每個資料塊可以包含多行。乙個完整的ins...

使用SQL語句 匯出SQLServer表結構

select 表名 case when a.colorder 1 then d.name else end,表說明 case when a.colorder 1 then isnull f.value,else end,字段序號 a.colorder,欄位名 a.name,字段說明 isnull g...

SQL Server資料庫映象的頁面自動修復原理

主庫頁面損壞 映象庫頁面損壞 lsn用來保證事務的時序 lsn儲存在每個資料頁面的頁頭 在同一臺機器,記憶體中的資料頁和磁碟中的資料頁保持同步依靠的是資料頁頭的lsn和事務日誌ldf檔案裡的lsn 當跨機器的時候,記憶體中的資料頁頭的lsn,主庫的ldf檔案,映象庫的ldf檔案,那麼在這三者就搭起了...