SQL Server資料庫中表和索引結構儲存的原理及如何加快搜尋速度分析

laozhang發表於2019-02-10

  本文詳細分析了SQL Server中表和索引結構儲存的原理以及對於如何加快搜尋速度和提高效率等方面做了詳細的分析,以下是主要內容。

  下圖顯示了表的儲存組織,每張表有一個對應的物件ID,並且包含一個或多個分割槽,每個分割槽會有一個堆或者多個B樹,堆或者B樹的結構是預留的。每個堆或者是B樹都有三個分配單元用來存放資料,分別是資料、LOB、行溢位,使用最多的分配單元是資料。如果有LOB資料或者是長度超過8000位元組的記錄,則可能有另外的LOB分配單元和行溢位分配單元。

  小總結: 一個表可以有多個分割槽,但是每個分割槽(堆/B樹)最多有三個分配單元,每個分配單元可以有很多頁,對於每個分配單元內的資料頁,根據表是否有索引,以及索引是聚集還是非聚集,組織方式有以下三種:

1. 堆

  所謂堆(heap),就是不含聚集索引的表。堆的 sys.partitions 中具有一行,對於堆使用的每個分割槽,都有index_id= 0。只有一個分割槽,在系統表裡,對於這個分割槽下面的每個分配單元都有一個連線指向Index Allocation Map頁(IAM),在IAM頁裡,描述了區的資訊。

  sys.system_internals_allocation_units系統檢視中的列first_iam_page指向管理特定分割槽中堆的分配空間的一系列 IAM 頁的第一頁。SQL Server 使用 IAM 頁在堆中移動。堆內的資料頁和行沒有任何特定的順序,也不連結在一起。資料頁之間唯一的邏輯連線是記錄在 IAM 頁內的資訊。

2. 具有非聚集索引的表

  如果有一個表只有非聚集索引而沒有聚集索引,對應的索引號是2--250。那麼針對每個非聚集索引,都有一個對應的分割槽,在系統表進而,對於這個分割槽下面的每個分配單元,都有一個連線指向根頁。資料頁之間透過前後指標互相聯絡,是一個完整的樹形結構。在樹的底層,會有一個連線指向真正的資料,連線的形式是檔案號+頁號+行號,而真正的資料是以堆的形式存放的。如下圖所示:

3. 具有聚集索引的表

  表中的聚集索引,對應的索引號是1。它有一個對應的分割槽,該分割槽下的每個分配單元都有一個連線指向根頁。對於聚集索引來說,葉子結點裡存放的是真正的資料,而不是非聚集索引那樣的連線。如下圖所示:

  非聚集索引與聚集索引具有相同的 B 樹結構,它們之間的顯著差別在於以下兩點:

  基礎表的資料行不按非聚集鍵的順序排序和儲存。

  非聚集索引的葉層是由索引頁而不是由資料頁組成

  案例分析: 我們來檢視一個表的儲存結構,我們在此使用的表是一個生產表,共有1億多條記錄,檢視錶的object_ID,如下圖所示:

  此表,我已經做了分割槽,檢視其分割槽資訊,可以使用下圖所示的命令:

  從上圖可以看到,此表共有16個分割槽,對應不同的索引,基本上每個分割槽都有1千多萬條記錄。從此圖中還可以看到堆或者B樹的ID跟分割槽ID是一樣的,如果希望進一步檢視某一個索引的具體資訊,可以使用下面的命令,如檢視72057594067419136的資訊。

  從這個圖當中,我們可以看到這個分割槽只有一個分配單元,IN_ROW_DATA表明此分配單元只用來存放具體資料,共5353頁,已使用5346頁,資料佔用5320頁。

  如果希望檢視根頁的位置,可以使用下面的命令:

  但需要注意,這裡顯示的根頁的位置是0xEC0100001100,由於儲存的關係,用倒序的方式對它進行解析,也就是0x0011000001EC,最前面的兩個位元組表明是所在的檔案組編號,後面的4個位元組是頁的編號,即(1,0x01CE) ,換成十進位制(1,492),然後可以利用我們上一節所說的DBCC PAGE命令檢視頁的資訊,如下圖所示:

  從中可以看到具體的資料,此介面的返回結果會因表上的聚集索引、非聚集索引而不同。如果檢視一個表使用的總頁數和區數,也可以使用命令:DBCC SHOWCONFIG,如下圖所示:

  在同樣表結構的情況下,建立聚集索引不會增加表格的大小,但是建立非聚集索引反而會增加不少空間,在效能方面,SQL Server產品組做過測試,在select、update、delete操作下,聚集索引效能較高,在插入記錄時,聚集索引和非聚集索引效能相同,沒有出現聚集索引影響插入速度的現象,但在生產環境中,還是要謹慎行事。

  原文連結:https://www.cnblogs.com/zxtceq/p/7920431.html

相關文章