SQL Server 索引基礎知識(1)--- 記錄數據的基本格式

通過總結,我發現自己以前很多很模糊的概念都清晰了很多。

  不論是緩存的數據信息,還是物理保存的信息,他們的基本單位都是數據頁。所以理解數據頁是最最基礎的知識點,本篇博客就介紹跟索引有關的數據頁的一些基礎知識。

  數據頁的基礎知識

  SQL Server 中數據存儲的基本單位是頁(Page)。數據庫中的數據文件(.mdf 或 .ndf)分配的磁盤空間可以從邏輯上劃分成頁(從 0 到 n 連續編號)。磁盤 I/O 操作在頁級執行。也就是說,SQL Server 每次讀取或寫入數據的最少數據單位是數據頁。

  注意:日誌文件不是用這種方式存儲的,而是一系列日誌記錄。

  數據庫被分成邏輯頁面(每個頁面8KB),並且在每個文件中,所有頁面都被連續地從0到x編號,其中x是由文件的大小決定的。我們可以通過指定一個數據庫ID、一個文件ID、一個頁碼來引用任何一個數據頁。當我們使用ALTER DATABASE命令來擴大一個文件時,新的空間會被加到文件的末尾。也就是說,我們所擴大文件的新空間第一個數據頁的頁碼是x+1。當我們使用DBCC SHRINKDATABASE或DBCC SHRINKFILE命令來收縮一個數據庫時,將會從數據庫中頁碼最高的頁面(文件末尾)開始移除頁面,並向頁碼較低的頁面移動。這保證了一個文件中的頁碼總是連續的。

  在 SQL Server 中,頁的大小爲 8 KB。這意味着 SQL Server 數據庫中每 MB 有 128 頁。依次類推。根據數據庫的文件大小,我們可以算出數據庫有多少數據頁。

  SQL Server 2005 有以下幾種頁類型:

頁類型內容Data當 text in row 設置爲 ON 時,包含除 text、 ntext、image、nvarchar(max)、varchar(max)、varbinary(max) 和 xml 數據之外的所有數據的數據行。Index索引條目。Text/Image大型對象數據類型:

  text、 ntext、image、nvarchar(max)、varchar(max)、varbinary(max) 和 xml 數據。

  數據行超過 8 KB 時爲可變長度數據類型列:

  varchar、nvarchar、varbinary 和 sql_variantGlobal Allocation Map、Shared Global Allocation Map有關區是否分配的信息。Page Free Space有關頁分配和頁的可用空間的信息。Index Allocation Map有關每個分配單元中表或索引所使用的區的信息。Bulk Changed Map有關每個分配單元中自最後一條 BACKUP LOG 語句之後的大容量操作所修改的區的信息。Differential Changed Map有關每個分配單元中自最後一條 BACKUP DATABASE 語句之後更改的區的信息。

  數據頁(Data 類型頁)的結構示意圖:

  每頁的開頭是 96 字節的標頭,用於存儲有關頁的系統信息。此信息包括頁碼、頁類型、頁的可用空間以及擁有該頁的對象的分配單元 ID。

  在數據頁上,數據行緊接着標頭按順序放置。頁的末尾是行偏移表,對於頁中的每一行,每個行偏移表都包含一個條目。每個條目記錄對應行的第一個字節與頁首的距離。行偏移表中的條目的順序與頁中行的順序相反。

有關數據頁的更多知識,可以通過下面這篇文章獲得更詳細的瞭解:

  估計在堆中存儲數據所需的空間量

  http://technet.microsoft.com/zh-cn/library/ms189124.aspx

  另外也可以看我收集的資料:怎樣查看錶的數據頁的結構

  http://blog.joycode.com/ghj/articles/113108.aspx

  對大型行的支持

  在 SQL Server 2005 中,行不能跨頁,但是行的部分可以移出行所在的頁,因此行實際可能非常大。

  (比如:一行多列時,這一行的部分列在數據頁A,部分列在數據頁B)

  頁的單個行中的最大數據量和開銷是 8,060 字節 (8 KB)。但是,這不包括用 Text/Image 頁類型存儲的數據。

  在 SQL Server 2005 中,包含 varchar、nvarchar、varbinary 或 sql_variant 列的表不受此限制的約束。

  當表中的所有固定列和可變列的行的總大小超過限制的 8,060 字節時,SQL Server 將從最大長度的列開始動態將一個或多個可變長度列移動到 ROW_OVERFLOW_DATA 分配單元中的頁。

  每當插入或更新操作將行的總大小增大到超過限制的 8,060 字節時,將會執行此操作。

  將列移動到 ROW_OVERFLOW_DATA 分配單元中的頁後,將在 IN_ROW_DATA 分配單元中的原始頁上維護 24 字節的指針。

  如果後續操作減小了行的大小,SQL Server 會動態將列移回到原始數據頁。

  SQL Server 的數據頁緩存

  SQL Server 數據庫的主要用途是存儲和檢索數據,因此密集型磁盤 I/O 是數據庫引擎的一大特點。此外,完成磁盤 I/O 操作要消耗許多資源並且耗時較長,所以 SQL Server 側重於提高 I/O 效率。緩衝區管理是實現高效 I/O 操作的關鍵環節。SQL Server 2005 的緩衝區管理組件由下列兩種機制組成:用於訪問及更新數據庫頁的緩衝區管理器和用於減少數據庫文件 I/O 的緩衝區高速緩存(又稱爲“緩衝池”)。

  

  緩衝區管理的工作原理

  一個緩衝區就是一個 8KB 大小的內存頁,其大小與一個數據頁或索引頁相當。因此,緩衝區高速緩存被劃分爲多個 8KB 頁。緩衝區管理器負責將數據頁或索引頁從數據庫磁盤文件讀入緩衝區高速緩存中,並將修改後的頁寫回磁盤。頁一直保留在緩衝區高速緩存中,直到已有一段時間未對其進行引用或者緩衝區管理器需要緩衝區讀取更多數據。數據只有在被修改後才重新寫入磁盤。在將緩衝區高速緩存中的數據寫回磁盤之前,可對其進行多次修改。

  實驗

  下面做一個簡單的實驗來看你是否已經掌握的上面的知識點:

  準備測試環境

  在一個SQL 2005數據庫中,執行下面腳本。

  簡單來說,就是創建了2個表,注意這兩個表,一個是存儲的 nchar(2019) 的字段,一個是存儲的 nchar(2020) 的字段。 我們將來看這兩個表在同樣數據下,存儲所花費的空間大小。由於緩存和物理存儲的基本單位都是數據頁,這個表物理存儲的大小跟全部緩存的大小會是一樣的。

  然後我們每個表填充20個數據。

  -- 創建2個測試表CREATE TABLE [dbo].[Table_2019]([Data] [nchar](2019) NOT NULL) CREATE TABLE [dbo].[Table_2020]([Data] [nchar](2020) NOT NULL) go-- 填充數據declare @i intset @i = 0while(@i < 20)begin insert Table_2019(Data) values('') insert Table_2020(Data) values('') select @i = @i + 1endgo

  這裏我們用 nchar 數據類型,是因爲:

  當指定了 NOT NULL 子句時,nchar 數據類型是一種長度固定的數據類型。

  如果插入值的長度比 nchar NOT NULL 列的長度小,將在值的右邊填補空格直到達到列的長度。

  例如,如果某列定義爲 nchar(10),而要存儲的數據是“music”,則 SQL Server 將數據存儲爲“music_____”,這裏“_”表示空格。

  http://technet.microsoft.com/zh-cn/library/ms175055.aspx

  這樣我們填充測試數據的腳本就非常簡單。

  而且計算數據行所佔的空間也非常簡單。

  另外,我們建立的這兩個表都沒有索引,所以他們都是堆,有關估計在堆中存儲數據所需的空間量請參看以下文章:

  http://technet.microsoft.com/zh-cn/library/ms189124.aspx

  完成準備工作後,我們來查看這兩個所佔空間的大小。在 SQL Server Management Studio 中,我們選擇測試數據庫, 然後在右鍵菜單中依次選擇

  Reports --> Standard Reports --> Disk Usage by Top Tables 或者Disk Usage by Table 就可以看到下面統計數據。

  Disk Usage by Top Tables: [ghj_Demo]

  on GHJ1976-PCSQLEXPRESS at 2007/12/27 9:21:33

  This report provides detailed data on the utilization of disk space by top 1000 tables within the Database.Table Name# RecordsReserved (KB)Data (KB)Indexes (KB)

  Unused (KB)dbo.Table_2020202001608

  32dbo.Table_201920136808

  48

  這兩個表同樣20條記錄。Table_2020 表數據佔了 160kb ,即 20 個數據頁。Table_2019 表數據佔了 80 kb,即 10 個數據頁。

  爲何會這樣呢?

  Table_2020 表的1個數據頁只能放下1個數據行。

  Table_2019 表的1個數據頁只能放下2個數據行。

  這兩個表的字段長度只差2個字節,但是物理存儲卻是一倍的差距。

 

發佈了44 篇原創文章 · 獲贊 7 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章