SQL Server中的索引內部結構:到SQL Server索引級別10的階梯

原文連接:http://www.sqlservercentral.com/articles/Stairway+Series/72442/sql

SQL Server中的索引內部結構:到SQL Server索引級別10的階梯數據庫

By David Durant, 2012/01/20數據庫設計

該系列函數

 

本文是樓梯系列的一部分:SQL Server索引的階梯sqlserver

 

索引是數據庫設計的基礎,而且告訴開發人員使用數據庫很是瞭解設計人員的意圖。不幸的是,當性能問題出現時,索引經常被添加爲過後考慮。最後是一系列簡單的文章,這些文章應該能讓任何數據庫專業人員迅速跟上他們的步伐性能

 

在之前的級別中,咱們已經對索引採起了一種合乎邏輯的方法,重點是它們能爲咱們作什麼。如今是時候採起物理方法,考察指標的內部結構了;爲了理解索引內部性,能夠理解索引開銷。只有瞭解索引結構,以及它是如何維護的,才能理解和最小化索引建立、更改和刪除的成本;以及行插入、更新和刪除。設計

 

所以,從這個層次開始,咱們將關注點擴大到包括索引的成本和索引的好處。畢竟,下降成本是利益最大化的一部分;最大化你的索引的好處就是這個樓梯的目的。3d

 

葉和葉水平指針

 

任何指數的結構都由葉級和非葉級組成。儘管咱們從未明確地說過,全部之前的水平都集中在指數的葉級上。所以,它是一個彙集索引的葉級,即表自己;每一個葉級條目都是表的一行。對於非彙集索引,它是包含每行一個條目的葉級(過濾後的索引除外);每一個條目由索引鍵列組成,可選包含列和書籤,其中要麼是彙集索引鍵列,要麼是RID(行ID)值。server

 

索引項也稱爲索引行;不管它是錶行(彙集索引葉級條目),都是指錶行(非彙集索引頁級),或指向較低級別的頁面(非葉級別)。

 

非葉級別是構建在葉級之上的結構,它使SQL Server可以:

 

在索引鍵序列中維護索引的條目。

 

快速查找給定索引鍵值的葉級行。

 

在第1級,咱們使用電話簿做爲類比來解釋索引的好處。咱們的電話簿用戶正在尋找「Meyer,Helen」,他知道條目會在任何排序的姓的中間,而後直接跳到白色頁面的中間開始搜索。然而,SQL Server並無這樣的內在的英語語言的名稱,或者其餘任何數據。它也不知道哪一個頁面是「中間」頁面,除非它從頭至尾把整個索引都走了。所以,SQL Server在索引中構建了一些額外的結構。

非葉水平

 

該附加結構稱爲索引的非葉級別或節點級別;它被認爲是創建在葉層之上,無論它的頁面在哪裏。它的目的是爲SQL Server提供每一個索引的單個頁面入口點,以及從該頁到包含任何給定搜索鍵值的頁面的一個簡短的遍歷。

 

索引中的每一頁,不管其級別如何,都包含索引行或條目。在頁級頁面中,正如咱們反覆看到的,每一個條目都指向一個錶行或者是錶行。所以,若是該表包含10億行,索引的葉級別將包含10億個條目。

 

在葉級以上的水平,即最低的非葉層;每一個條目指向一個葉級頁面。若是咱們的10億條目索引平均每一頁有100個條目,對於一個索引的搜索鍵包含幾個數字、日期和代碼列,這是一個現實的數字;而後,葉級將包含10 000,000,000 / 100 = 10,000,000頁。反過來,最低的非葉級將包含10,000,000個條目,每一個條目指向一個葉級頁面,而且將跨越100,000頁。

 

每一個較高的非葉級都有頁面,每一個頁面的條目都指向下一級的頁面。所以,咱們的下一個更高的非葉級別將包含100,000個條目,並有1000頁大小。上面的級別包含1000個條目,大小爲10頁;上面的那一頁只有一頁上有10個條目;這就是它中止的地方。

 

位於索引頂部的惟一頁面稱爲根頁。位於根頁級和葉級以上的索引的級別稱爲中間層。等級的編號從零開始,從葉級開始向上。所以,最低的中級水平老是1級。

 

非葉級條目只包含索引鍵列和指向較低級別頁面的指針。包含的列只存在於葉級條目中;它們不在非葉級條目中。

 

除了根頁面以外,索引中的每一個頁面都包含兩個額外的指針。這些指針指向下一頁和上一頁,在索引序列中,在同一級別上。由此產生的雙向鏈表使SQL Server可以以升序或降序的順序掃描任何級別的頁面。

 

一個簡單的例子

 

下面的圖1所示的簡單圖幫助說明了這種樹狀結構的索引。此圖表示一個在理論人員的LastName / FirstName列上建立的索引。使用如下SQL:Employee表:

CREATE NONCLUSTERED INDEX IX_Full_Name
ON Personnel.Employee
(
LastName,
FirstName,
)
GO
圖注:
 
指向頁面的指針包括數據庫文件號和頁碼。所以,指針值爲5:4567指向數據庫文件# 5的4567頁。
 
大多數樣本值已經從人身上取走了。在AdventureWorksdatabase中聯繫表。還增長了一些用於說明的目的。
 
卡爾·奧爾森是這個例子中最受歡迎的名字。有這麼多的Karl Olsens,他們的條目跨越了一個完整的中間水平索引頁。

圖1 -索引的垂直切片
 
爲了清晰和說明,圖表與一個典型的指數不一樣的是:
 
一個典型索引中的每一個頁面的條目數將大於圖中所示的數字,所以,除了根以外,每一個級別的頁數都大於顯示的頁數。葉級,特別是,將有遠多於能夠顯示在咱們的空間有限圖。
 
實際索引的條目不在頁面上進行排序。這是頁面的條目偏移指針,它提供對條目的排序訪問。(請參閱第4級-頁面和擴展,以得到關於偏移指針的更多信息。)
 
一般狀況下,索引的物理和邏輯序列之間的相關性比圖表中顯示的要多。該索引的物理和邏輯序列之間缺少相關性稱爲外部碎片,並在第11級-分段中討論。
 
如前所述,索引能夠有多箇中間級別。
 
就好像咱們的白頁用戶正在尋找海倫·邁耶,打開電話簿,發現第一頁,只有第一頁,是粉紅色的。在「粉紅頁面」的排序列表中,有一個條目是「在費爾南德斯、塞爾達和奧爾森之間的名字」,「看藍頁5:431」。當咱們的用戶瀏覽到藍頁5:431的時候,頁面上的一個條目上面寫着「庫瑪爾,凱文」和「奈良」之間的名字,參見「白色頁5:2006」。粉色的頁面對應於根,藍色的頁面對應中間的層次,而白色的頁面是葉子。

指數深度

 

根頁面的位置存儲在系統表中,以及其餘關於索引的信息。每當SQL Server須要訪問與索引鍵值相匹配的索引項時,它就從根頁面開始,並在索引的每一個級別上經過一個頁面進行工做,直到到達包含該索引鍵的條目的葉級頁面爲止。在咱們的10億行表示例中,5頁的讀取將把SQL Server從根頁帶到葉級頁面及其所需的條目;在咱們的圖表示例中,三個讀取就足夠了。在彙集索引中,這個葉級條目將是實際的數據行;在非彙集索引中,該條目將包含彙集索引鍵列或RID值。

 

索引的級別或深度的數量取決於索引鍵的大小和條目的數量。在AdventureWorks數據庫中,沒有索引的深度大於3。在具備很是大的表或很是寬的索引鍵列的數據庫中,可能會出現6個或更大的深度。

 

sys。dm_db_index_物理cal_statsfunction提供關於索引類型、深度和大小等索引的信息。它是一個可查詢的表值函數。清單1中顯示的示例返回SalesOrderDetailtable的全部索引的彙總信息。

SELECT OBJECT_NAME(P.OBJECT_ID) AS 'Table'
     , I.name AS 'Index'
     , P.index_id AS 'IndexID'
     , P.index_type_desc 
     , P.index_depth 
     , P.page_count 
  FROM sys.dm_db_index_physical_stats (DB_ID(), 
                                       OBJECT_ID('Sales.SalesOrderDetail'), 
                                       NULL, NULL, NULL) P
  JOIN sys.indexes I ON I.OBJECT_ID = P.OBJECT_ID 
                    AND I.index_id = P.index_id;

清單1:查詢系統。dm_db_index_物理cal_stats函數,如圖2所示。

 

圖2:查詢系統的結果。dm_db_index_physical_stats函數

 

相反,清單2中所示的代碼請求特定索引的詳細信息,即SalesOrderDetail表中表中惟一的非彙集索引。它返回每一個索引級別的一行,如圖3所示。

 

清單2:查詢系統。dm_db_index_physical_stats詳細信息。

SELECT OBJECT_NAME(P.OBJECT_ID) AS 'Table'
     , I.name AS 'Index'
     , P.index_id AS 'IndexID'
     , P.index_type_desc 
     , P.index_level  
     , P.page_count 
  FROM sys.dm_db_index_physical_stats (DB_ID(), OBJECT_ID('Sales.SalesOrderDetail'), 2, NULL, 'DETAILED') P
  JOIN sys.indexes I ON I.OBJECT_ID = P.OBJECT_ID 
                    AND I.index_id = P.index_id; 
圖3:查詢系統的結果。dm_db_index_physical_stats爲詳細信息

 

從圖3所示的結果中,咱們能夠看到:

 

該指數的葉級分佈在407頁。

 

一個和惟一的中級水平只須要兩頁。

 

根級別始終是一個單獨的頁面。

 

指數的非葉部分的大小一般是葉級的十分之一到百分之一。根據哪些列包含搜索鍵、書籤的大小,以及是否指定了包含列的列。換句話說,相對而言,索引很是寬且很是短。這與大多數的索引示例圖不一樣,例如圖1中的圖,它一般是高的和窄的。

結論

 

索引結構使SQL Server可以快速訪問特定索引鍵值的任何條目。一旦找到該條目,SQL Server就能夠:

 

訪問該條目的行。

 

從這一點經過升序或降序遍歷索引。

 

這種索引樹結構已經使用了很長時間,甚至比關係數據庫還要長,並且它已經證實了本身的時間。

 

記住,包含的列只適用於非彙集索引,它們只出如今葉級條目中;它們從更高級別的條目中被忽略,這就是爲何它們不會增長非葉級別的大小。

 

因爲彙集索引的葉級是表的數據行,因此只有彙集索引的非葉部分是額外的信息,須要額外的存儲。數據行將存在是否建立索引。所以,建立集羣索引可能須要時間和消耗資源;可是,當建立完成時,數據庫中消耗的額外空間不多。

相關文章
相關標籤/搜索