SQL Server中數據的存儲


      我們知道,目前的關系型數據庫都是將文件存儲在物理磁盤上面,既然是存儲在磁盤上面,那么就會涉及到數據存儲問題。本文我們主要探討數據庫中數據的存儲。

      與數據庫有關的文件有3種,即主數據庫文件,次數據庫文件和數據庫日志文件。主數據庫文件和次數據庫文件里面存儲的是我們的數據和對象,例如表,視圖,存儲過程等等,是我們程序所要用到的。數據庫日志文件包含恢復數據庫所需的完整的事務信息,日志文件平時並沒有什么特殊的用途,只是記錄對數據庫的操作,但是當數據庫發生誤操作或者錯誤甚至是災難性的后果時,日志文件就能派上用場。三種數據庫文件如下:

文件 說明
主要 主要數據文件包含數據庫的啟動信息,並指向數據庫中的其他文件。用戶數據和對象可存儲在此文件中,也可以存儲在次要數據文件中。每個數據庫有一個主要數據文件。主要數據文件的建議文件擴展名是 .mdf。
次要

次要數據文件是可選的,由用戶定義並存儲用戶數據。通過將每個文件放在不同的磁盤驅動器上,次要文件可用於將數據分散到多個磁盤上。另外,如果數據庫超過了單個 Windows 文件的最大大小,可以使用次要數據文件,這樣數據庫就能繼續增長。

次要數據文件的建議文件擴展名是  .ndf。
事務日志 事務日志文件保存用於恢復數據庫的日志信息。每個數據庫必須至少有一個日志文件。事務日志的建議文件擴展名是 .ldf。

1 文件組(filegroup)

      文件組是一個邏輯概念,一個數據庫可以包含多個文件組,一個文件組可以包含多個物理數據庫文件,每個數據庫至少有一個文件組,一個文件組里面至少有一個文件,這就是我們在創建數據庫的時候默認的情形。數據庫文件組如下圖所示:

          那有人會問,為什么要有文件組的概念呢,文件組的作用是什么?通常情況下,有兩種情形可以使用文件組:

      1)在大型的應用程序中,數據庫中存儲的數據量也會很大,可能達到幾十幾百GB,甚至達到數TB,那在這種情況下,用單個數據庫文件存儲數據,就會出現如索引慢等問題,性能出現瓶頸。這時使用文件組就能比較好的解決這個問題,因為文件組中的某個表,其中的數據會分布在這個文件組所有物理文件中,因此,如果將文件組包含的文件建在不同的磁盤下,那么對一個表的查詢將會分散到多個磁盤上,這樣就提高了查詢效率。

      2  在某些場景中,需要對業務進行划分,每一塊業務相對獨立,這個時候可以使用文件組將數據庫中的各個業務的數據分開,這時,只需要將各自業務下的表和對象創建在該業務對應的文件組里即可。

      文件組中的文件可能分布在各個文件夾下,但是這些文件是一個邏輯整體,文件組中的任何文件都缺一不可,因此如果將文件組中的文件做遷移的時候要注意,不要將某個文件遺漏,否則數據庫將無法運行。另外說一點就是文件組里面可以包含主數據庫文件,次數據庫文件,但是不能包含日志文件。

2 區段(extent)

      區段是用來為表和給定文件中的索引分配空間的基本存儲單元。它由8個連續的大小為64KB的數據頁組成,即大小為512KB。

      關於區段的要點包括:

      1)  一旦一個區段已滿,那么下一條記錄將占用一個完整的新區段大小,而不是記錄本身的大小。我們可以理解為SQL Server每次分配的空間是一個區段的大小。

      2)  通過預先分配空間,SQL Server省下了為每一條記錄分配新空間的時間。

僅僅因為要添加的行比現在分配的區段所能容納的行多了一行,就要另外占用整個區段,這似乎是一種浪費。但是,這種方式浪費的空間總量通常並不會那么多,只占了數據庫空間很小的比例,但是在高碎片化的環境中,這種浪費可能就比較多了。

      占用整個區段空間的好處是SQL Server省去了一些分配空間的時間上的開銷。SQL Server不必每寫入一行就考慮分配問題,而是在需要新的區段時才處理額外空間的分配。

3 頁(page)和頁拆分

      與區段是數據庫中的分配單元類似,頁是區段的分配單元。每一個區段包含8個頁,每個頁的大小為8KB。

頁是到達真正的數據行的最后一個級別。盡管每個區段中頁的數量是固定的,但是頁中的行數是不固定的,這個取決於行的大小,是可變的。可以把頁想成是表和索引行數據的某種容器。數據行是不允許跨頁的。頁的結構如下圖所示:

      上圖展示了數據是如何存放在頁中的。對於插入的每一行,為了表明特定行的數據開始於頁中的何處,每一頁的末尾都用一小塊空間記錄的每一行相對於頁頭位置的偏移量。

            SQL Server中的頁有很多種類型,如索引頁,數據頁等,這里只是一提,不做具體討論。

      當頁滿時,會對其做拆分。在拆分頁時,會創建一個新頁,並將已滿的頁上大約一半的數據移動到新頁上存儲。但是這也有例外,那就是使用聚集索引的時候。當在表上創建了聚集索引,而且下一個插入的行物理上位於表的最后一行時,那么將創建一個新頁並把新的行添加到新的頁上,不會把已滿的行上一半的數據移動到新頁上面。關於頁拆分的更深入的探討,我會在下一篇博客《SQL Server中的索引》中詳細呈現,敬請關注^_^。

4 行(row)

      行是數據存儲的單位,在SQL Server中,行的大小限制在8KB(8060個字符,此時,頁上只有1條記錄),行中最大的列數限制在1024列。在數據頁上,列最大的限制是8KB(此時的記錄是1行1列,並且頁上面只有1條記錄),這應該就是SQL Server中varchar類型數據最大只能是8000的緣故吧。

5 參考資料

      1)  《SQL Server 2008高級程序設計》 (美)Robert Vieira著,清華大學出版社。

      2)  SQL Server 2008聯機叢書。

      3)  MSDN。

6 結語

      本篇博客已經寫完了,這是行客第一次真正寫完一篇技術博客。在寫博客的過程當中,有些知識點不是很確定還參考了一些資料。限於本人水平,文中難免有紕漏或者某些地方沒有表述清楚,望讀者見諒!在閱讀過程中如有發現錯誤或表述不清的地方,望不吝指教,謝謝!

      讀者若想做更深入的了解,建議去MSDN或者查看聯機叢書。

      另外,本篇文章系原創,轉載請注明出處,謝謝!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM