1. 程式人生 > >T-SQL執行內幕(8)——資料儲存

T-SQL執行內幕(8)——資料儲存

本文屬於SQL Server T-SQL執行內幕系列


    前面提到了資料訪問,那麼如何訪問?訪問什麼?為此必須介紹一下資料儲存的概念。SQL Server以三種方式儲存和組織資料:均可從sys.partitions中查到

  • Heaps:堆,指沒有聚集索引(注意主鍵並非一定是聚集索引)的表。另外諸如select …into … from …語句生成的表也是堆表。SQL Server堆結構

    在sys.partitions中每個堆表有一行對應的值,其中index_id為0。從SQL 2005開始,預設情況下,一個堆表就是一個分割槽,如果一個堆表有多個分割槽,那麼每個分割槽都包含一個堆結構。堆表資料沒有順序。或者說,除非明確在語句中使用Order by子句,否則不能保證結果集的順序。通過掃描IAM頁可以進行堆的表掃描或序列讀取,序列堆掃描會按順序掃描每個檔案,意味著堆中的行不會按照插入時的順序返回。

  •  Clustered Index:聚集索引,也叫聚集表,與堆表相對,雖然叫“索引”,但是實際上它是表的另外一種組織方式(B-Tree,B樹),也就是說它還是表本身,只是一個表要麼是堆表,要麼是聚集表,兩者不可共存。SQL Server 聚集索引結構

    索引中的頁稱為一個索引節點。B樹頂部的節點為根節點。最底部的節點為葉子節點聚集索引的葉子節點包含了表的實際資料頁。根及中間節點包含多個索引行的索引頁,每個索引行包含一個鍵值和指向其他中間結點頁的指標或者指向葉子節點的資料行。並且每級節點使用雙向列表互相關聯。

    聚集索引在sys.partitions中有index_id=1的行一一對應每個分割槽。預設一個聚集索引就是一個分割槽。如果有多個分割槽,每個分割槽包含一個獨立的聚集索引。 

  • Nonclustered Index:非聚集索引,與前面兩種不一樣的是,堆表和聚集表都可以有非聚集索引,而且通常它並不包含表本身的所有資料。更多的是一個數據表的“子集”,我們在效能優化和資料庫設計中常說的索引大部分情況下就是非聚集索引。同樣,它也是B-Tree結構。SQL Server非聚集索引結構

    從SQL Server 2012開始,引入了另外一種資料組織結構——列式儲存,相對於聚集索引和非聚集索引這種B-Tree結構,2012只有非聚集列式儲存(Nonclustered Columnstores),2012之後的版本引入了聚集列式儲存(Clustered Columnstore)。更多內容可以參考:

http://rusanu.com/2012/05/29/inside-the-sql-server-2012-columnstore-indexes/http://rusanu.com/2013/06/11/sql-server-clustered-columnstore-indexes-at-teched-2013/

術語說明:

    頁、區:

    這是資料實際儲存的單位,頁為8K,區為連續的8個頁。8個連續的頁會組合成一個區。區不能小於8個頁。SQL Server包含混合區和統一區兩類區。在混合區中,每個頁可以分配給不同的物件,比如當一個表初次建立,並且資料足夠存放在少於8個頁中時,SQLServer會建立一個混合區來存放這些頁。當表的資料越來越多,8個頁無法滿足儲存時,SQL Server會合並混合區成為一個統一區。

    注意:如果一個表增長到8個頁以上,那麼前8個頁還是存在於混合區,從第九個頁開始才分配統一區,除非重建表(比如rebuild table)。


    B-Tree

    是一種平衡樹資料結構,用於位置資料順序和允許搜尋、順序訪問、插入和刪除操作。專為讀寫大塊資料的系統而設計。B樹是反過來的一棵樹,最頂端只有一個節點,稱為根節點,最低端稱為葉子節點,中間的各級節點統稱中間節點。

    IAM:Index Allocation Map 

    這個頁對於索引來說非常重要,SQL Server經常需要知道特定表或者索引上是否有頁關聯,而這些資訊存放在IAM頁中。每個表或者索引都從IAM頁開始,並標識存放在GAM的哪個區,如果一個表或者索引跨了多個GAM,就會有多個IAM頁關聯。IAM頁有4類頁面關聯,資料頁、索引頁、LOB物件和small-large物件頁。它們在IAM的bit中體現。

 對於頁的研究,強烈推薦一個很好的工具:InternalsViewer for SQL Server,下載地址:http://internalsviewer.codeplex.com/這是一個圖形化的工具,可以通過圖形化的介面來粗略瞭解區、頁的情況,對於入門級別的讀者來說相當有效。不過比較遺憾的是目前只支援到2008。

總結

    資料儲存組成了資料庫的“空間”概念,空間的大小最精確的統計就是統計頁的數量,當然如果你要走極端,統計行的bytes數更加準確。資料型別、行數、列數又影響了頁的大小,碎片情況又影響了區的大小。

    空間問題,又從根本上制約了效能,所以在設計和程式設計過程中,多考慮資料型別的使用非常重要。

    更多詳細資訊可以參考本人書籍《SQL Server效能優化與管理的藝術》一書第六章。