深入理解Sqlserver檔案儲存體之頁和應用

來源:互聯網
上載者:User

標籤:

我們每天都在使用資料庫,我們部門使用最多的關聯式資料庫有Sqlserver,Oracle,有沒有想過這些資料庫是怎麼存放到作業系統的檔案中的?有時候為了能夠設計出最優的表結構,寫出高效能的Sqlserver指令碼,處理海量資料並發,我們必須解底層原理。由於個人興趣最近研究了下Sqlserver的檔案儲存體,由於水平有限,下面只講解Sqlserver的最小儲存單元-頁。

什麼是頁,區?

什麼會有一個頁的概念,我們知道對於作業系統來說,檔案可以認為是一個很大 的線性空間,如果按地址空間順序分配容量(也就是按段式儲存),則有可能會造成很多的外部片段,造成很多的容量很難再次使用,只有移動合并空間才能騰出更 多的空間。例如:如下表所有,如果我現在要申請1024B位元組的空間,顯然下面的兩個空間空間單個計算不夠,合起來卻是夠用的的,只能移動合并空間。

8KB

512B

12KB

512B

8KB

已指派空間

空閑

已指派空間

空閑

已指派空間

表1

為了能夠更好的利用磁碟空間,Sqlserver借鑒了作業系統的虛擬記憶體的概念,人為的將檔案劃分N個8KB的儲存空間,這樣每次分配時,都是按照8KB空間申請,就解決了外部片段的問題,也就是說Sqlserver 中資料存放區的基本單位,頁的大小為8KB,每頁的開頭是96位元組的標題用於儲存有關頁的儲存資訊,其中有頁碼、頁類型、頁的可用空間以及擁有該頁對象的配置單位ID。上述的例子分配就成為下表所示:這樣就解決了外部片段問題。

業內分配

8kB

12KB

8KB

xxKB

頁單元

8KB

8KB

8KB

8KB

空閑

表2

為什麼會有區的概念,已經有了頁的單位難道不夠嗎?主要是為了更好的管理這些空間,Sqlserver將每8個頁劃分為一個區(如下表所示)就像百元大鈔代表著100個10元人民幣一樣,出去買很多東西時,用百元大鈔比用很多1元錢要方面。

一個分區

頁1

頁2

頁3

頁4

頁5

頁6

頁7

頁8

表3

為了有個頁有更具體的認識,下表為頁頭的結構:

 

圖-1

行是怎麼在頁中儲存的?

那麼資料庫中的資料到底是以什麼樣的形式儲存在資料中的呢?Sqlserver是以行為單位儲存的資料,也就是說表中的每條資料(每行資料為一個塊)順序存放在頁中的,那麼怎麼找到行?也就是一行的開始地址和結束位址? Sqlserver在每頁的末尾以2個位元組為單位存放了每行的開始地址,這樣我們就可以定位到行的開始,通過下一條的開始位置能夠知道本條記錄的結束位置,這樣我們就可以取出這行資料了。

圖-2

,如果我想取第二條資料,那麼現將一頁資料都讀到記憶體中,然後從最後讀取位移為第3開始開始讀取2個位元組,怎麼可以找到行2的開始位置,同理可以讀取出行2的結束位置。

列是怎麼在頁中的儲存?

現在我們已經讀取到行了並且已經在記憶體裡了,接下來怎麼解析出一行中的所有列?也就是這些列是怎麼存放的?資料庫表中的列無非就兩種情況:定長列、變長列。

首先假設只有定長列,那麼很容易想到一樣中的每列的之順序存放就行了,因為是定長的,完全可以將每列的位移放到另外一個地方單獨儲存,如果要取某個特定的列,每個列的位置很容易定位:如下表所示:

2位元組

3位元組

6位元組

10位元組

3位元組

2位元組

1

23

55

A

C

D

表-4

如果要取紅色的資料,那麼它的

 開始位置=(行開始位置)+ 2位元組+3位元組+6位元組+10位元組。

 結束位置= 開始位置 + 3位元組。

其中每個列的長度完全可以用另一張表存放

1

2

3

4

5

6

長度(位元組)

2

3

6

10

3

2

表-5

具體行結構的詳細資料如下:

 

圖-3

假如設計的表結構為 :

Col1

Col2

Col3

Col4

Char(5)(not null)

Int (null)

Char(3)(null)

Char(6)(not null)

表-6

在資料庫中存放資料為:

Col1

Col2

Col3

Col4

‘ABCDE’

‘123’

‘null’

‘ccc ‘

表-7

則資料在資料庫檔案中資料以如下形式存在:

 

圖-4

 

如果其中有變長列呢,這個結構又是怎麼儲存的?有變長列最大的不同就是每個列的長度是不定的(同一列,每行長度都不一樣),也就是不能用另外一張表存放。那麼我們只能把列的長度放在行內了。這樣就解決了實際長度定位的問題,上面已經說過,sqlserver有一個行位移矩陣。

如果我們定義的表結構如下:

Col1

Col2

Col3

Col4

Col5

Char(2)(not null)

Varchar(250)(not null)

Varchar(5)(null)

Varchar(20)(not null)

Small int (null)

表-8

假如這行資料為:

Col1

Col2

Col3

Col4

Col5

‘AAA’

RELICATE(‘X’,250)

null

‘ABC’

123

表-9

則資料在資料庫中實際的存放形式為:

 


圖-5

結論:

1.資料庫列中盡量不用可空類型,當值為空白時,實際不佔用位置,並且也不能作為索引的索引值。導致where語句中含有 is null 或者 is not null 時只能進行全表掃描,並且可空類型也容易導致Null 參考異常。

2.在設計列時,只有列長度確定的才用定長,比如身份證。其他情況基本上應該用varchar邊長類型,不但節省空間的同時,一個頁存放的資料會變多。導致同樣的資料量讀取頁的次數變少,減少I/O,提高效能。

3.-1所示,聚簇索引不是按物理順序存放的,是按邏輯物理順序存放的(大多數人在這裡會有誤解。)

4.正常情況下不要使用varchar(max),因為這個列的資料肯定放不在一個頁裡,為瞭解決這個問題,sqlserver在列裡只存放了一個指標。真正的資料放在了其他多個頁裡。每讀取一行中的列都會至少多一次I/O,影響效能。

附註,參考資料:

(1) Microsoft SQL Server 2005技術內幕:儲存引擎(中文)

(2)微軟MSDN: http://msdn.microsoft.com/zh-cn/library/ms190969(v=sql.105).aspx

深入理解Sqlserver檔案儲存體之頁和應用 (轉)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.