深刻非彙集索引:樓梯SQL Server二級索引

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

 

Deeper into Nonclustered Indexes: Stairway to SQL Server Indexes Level 2

By David Durant, 2017/10/18 (first published: 2014/11/26數據庫

深刻非彙集索引:樓梯SQL Server二級索引

經過大衛·杜蘭特,2017/10/18(第一次出版:2014/11/26)服務器

該系列

本文是樓梯系列的一部分:SQL Server的階梯索引數據庫設計

索引數據庫設計的基礎,告訴開發人員使用數據庫設計者的意圖。 不幸的是索引時每每是後加上的性能問題出現。 終於在這裏是一個簡單的系列文章,應該讓任何數據庫專業迅速加速sqlserver

SQL Server的一級索引樓梯介紹了SQL Server索引,通常來講,和非彙集索引。 做爲咱們的第一個案例研究中,咱們演示了索引的潛在好處,當從一個表中檢索單個行。 在這個層面上,咱們繼續咱們的調查的非彙集索引; 檢查他們的貢獻好的查詢性能的狀況下,超越從一個表中檢索單個行。性能

將在大多數咱們的水平,咱們引入少許的理論,研究一些指數內部爲了幫助解釋這個理論,而後執行一些查詢。 有或沒有執行這些查詢索引和性能報告統計數據,這樣咱們能夠查看指標的影響。測試

咱們將使用從AdventureWorks數據庫表的子集,咱們用於一級、集中聯繫表在這個水平。 咱們將使用一個指數FullName咱們用於一級指數,來講明咱們的觀點。 以確保咱們控制上的索引聯繫表,咱們會讓兩個表的副本dbo模式,只有構建FullName指數其中之一。 這將給咱們的控制環境:兩份表:一個與一個單一的非彙集索引,一個沒有任何索引。spa

注意:
全部TSQL代碼所示這樓梯水平能夠在文章底部的下載。設計

清單1中的代碼的副本Person.Contact,咱們能夠隨時從新運行這個批處理咱們但願從一個白紙開始。指針

若是存在(選擇*sys.tables&# 160;在哪裏OBJECT_ID=OBJECT_ID(「dbo.Contacts_index」))刪除表dbo.Contacts_index;若是存在(選擇*sys.tables&# 160;在哪裏OBJECT_ID=OBJECT_ID(「dbo.Contacts_noindex」))刪除表dbo.Contacts_noindex;選擇*dbo.Contacts_indexPerson.Contact;選擇*dbo.Contacts_noindexPerson.Contact;

清單2.1:複製人。 聯繫表

的一個片斷聯繫人表所示:

ContactID FirstName MiddleName LastName EmailAddress


1288年勞拉·F·諾曼laura1@adventure-works.com
651年邁克爾彭定康michael20@adventure-works.com
1652伊莎貝拉R詹姆斯isabella6@adventure-works.com
1015年大衛·R·坎貝爾david8@adventure-works.com
1379Balagane Swaminath balaganesan0@adventure-works.c
742年史蒂夫施密特steve3@adventure-works.com
1743年香農Cshannon16@adventure-works.com
1106年約翰·Yjohn2@adventure-works.com
1470年布萊恩Dockter blaine1@adventure-works.com
833年克拉倫斯·RTatman clarence0@adventure-works.com
1834希瑟·heather6@adventure-works.com
丹尼斯·H·史密斯1197 denise0@adventure-works.com
560年詹妮弗·JMaxham jennifer1@adventure-works.com
1561年被罩Ben-Sacha ido1@adventure-works.com
924年貝基R。 水域becky0@adventure-works.com

非彙集索引條目

下面的語句建立咱們的Contacts_index FullName非彙集索引表。

建立索引FullNameContacts_index(,FirstName);

清單2.2 -建立一個非彙集索引

記住一個非彙集索引存儲索引鍵,以及一個書籤用來訪問表中的實際數據自己。 你能想到的書籤做爲一種指針。 將來的水平將描述書籤,其形式和使用,詳細。

的一個片斷FullName指數顯示,組成的姓和FirstName做爲鍵列,加上書籤:

——搜索鍵列:書籤

Russell          Zachary                  =>  
Ruth             Andy                     =>  
Ruth             Andy                     =>  
Ryan             David                    =>  
Ryan             Justin                   =>  
Sabella          Deanna                   =>  
Sackstede        Lane                     =>  
Sackstede        Lane                     =>  
Saddow           Peter                    =>  
Sai              Cindy                    =>  
Sai              Kaitlin                  =>  
Sai              Manuel                   =>  
Salah            Tamer                    =>  
Salanki          Ajay                     =>  
Salavaria        Sharon                   =>  每一個條目包含索引鍵列和收藏價值。 此外,SQL Server非彙集索引條目有internal-use-only頭信息和可能包含一些可選的數據值。 這些將在之後的水平; 也不是重要的在這個時候非彙集索引的基本理解。

如今,咱們須要知道的是,鍵值使SQL Server可以找到合適的索引條目(年代); 和條目的收藏價值使得SQL Server訪問相應的數據表中的行。

索引條目的好處在序列

索引條目排序的索引鍵值(s),那麼SQL Server能夠快速遍歷順序條目。 的掃描序列條目能夠開始從一開始的指數,指數,指數中或從任何條目。

所以,若是一個請求要求全部聯繫人的姓開頭字母「S」(LastName' S % '),SQL Server能夠快速導航到第一個「S」條目(「Sabella,迪安娜」),而後遍歷索引,使用書籤訪問的行,直到到達第一個「T」條目; 這時它知道它檢索全部的「S」條目。

上述請求執行更快若是全部選中的列索引。 所以,若是咱們發佈:

選擇FirstName,聯繫在哪裏就像' S %;

SQL Server能夠快速導航到第一個「S」條目,而後遍歷索引條目,忽略了書籤和檢索數據值直接從索引條目,直到它到達第一個「T」條目。 在關係數據庫術語中,該指數覆蓋查詢。

任何SQL操做符的好處從測序數據能夠從索引中受益。 這包括ORDER BY、組,不一樣的聯盟(聯盟),並加入

例如,若是請求要求計數的聯繫人的姓,SQL Server能夠在第一項開始計數,並進行指數。 每次姓的價值變化,SQL Server輸出當前計數,並開始一個新的計數。 與前面的請求,這是一個覆蓋查詢; SQL Server訪問索引,徹底忽略了表。

注意從左到右的順序的重要性的關鍵列。 咱們的指數是很是有用的,若是一個請求要求每一個人的姓艾什頓」,但不多或根本沒有幫助若是請求是對每一個人都是誰的名字艾什頓

測試一些示例查詢

若是你想執行測試查詢,確保你運行該腳本建立兩個版本新聯繫表,dbo.Contacts_indexdbo.Contacts_noindex;建立並運行腳本名,姓指數dbo.Contacts_index

驗證斷言在前面的小節中,咱們將在相同的性能統計數據,咱們使用1級和運行一些查詢; 有和沒有索引。

設置數據io

 

設置數據時間

由於聯繫人表的AdventureWorks數據庫中只有19972,它將很可貴到有意義的統計值。 咱們大多數的查詢會顯示CPU時間值爲0,因此咱們不顯示統計數據的輸出時間; 只從統計數字IO,反映了可能的頁面數量必須閱讀。 這些值將使咱們可以比較查詢在相對意義上,肯定哪些查詢與索引比別人表現得更好。 若是你想要一個更大的表更現實的計時測試,腳本構建版本的一百萬行聯繫本文表是可用的。 全部的討論將假設您使用的是標準的19972 -行表。

測試覆蓋查詢

咱們的第一個查詢將被索引的查詢; 一個檢索一組有限的列的全部聯繫人的姓始於「S」。 表2.1中給出了查詢執行信息。

SQL

選擇FirstNameLastName
dbo。 聯繫人——Contacts_noindex和執行
——Contacts_index
LastName' S %

沒有索引

(2130行受影響)
「Contacts_noindex」。 掃描數1,邏輯讀568

與指數

(2130行受影響)
「Contacts_index」。 掃描數1,邏輯讀14

指數的影響

568年讀14IO減小。

評論

覆蓋索引查詢是一件好事。 沒有索引,找到掃描整個錶行。
「2130的統計數據代表,「S」是一個流行的姓氏首字母,發生在百分之十的聯繫人。

2.1:覆蓋查詢運行時執行結果

測試一個Non-Covered查詢

接下來,咱們修改咱們的查詢請求與以前相同的行,但不包括列索引。 表2.2中給出了查詢執行信息。

SQL

SELECT *
dbo。 聯繫人——Contacts_noindex和執行
——Contacts_index
LastName' S %

沒有索引

與以前的查詢相同。 (由於它是一個表掃描)

與指數

(2130行受影響)
「Contact_index」。 掃描數1,邏輯讀568

指數的影響

根本沒有影響。

評論

該指數是查詢的執行期間從未使用過!
SQL Server決定從索引項跳到相應的表中的行2130次爲每一行(曾經)是更多的工做比掃描整個表的一百萬行找到須要的2130行。

2.2:non-covered查詢運行時執行結果

測試一個Non-Covered查詢但更有選擇性

這一次,咱們讓咱們的查詢更多的選擇性; 也就是說,咱們縮小被請求的行數。 這增長的機率指數將有利於查詢。 表2.3中給出了查詢執行信息。

SQL

SELECT *
dbo。 聯繫人——Contacts_noindex和執行
——Contacts_index
LastName「Ste %」

沒有索引

與以前的查詢相同。 (由於它是一個表掃描)

與指數

(107行受影響)
「Contact_index」。 掃描數1,邏輯讀111

指數的影響

IO減小從568年讀111. .

評論

SQL Server 107年訪問「Ste %」條目,都是坐落在指數連續。 每一個條目的書籤被用來檢索到相應的行。 行不位於連續在桌子上。

這個查詢索引受益; 但不是它受益第一個查詢,查詢覆蓋」; 尤爲是所須要的IOs數檢索每一行。

你可能會認爲,閱讀107索引條目須要107 + 107 + 107行。 爲何只有111讀取被要求將覆蓋在一個更高的水平。 如今,咱們不多會說,讀的是用於訪問索引條目; 大部分被用來訪問的行。

由於前面的查詢請求的2130,沒有受益於指數; 這個查詢,要求107,受益於指數——您可能還想臨界點又在何方? 「SQL Server的決定背後的計算也將在將來的水平。

2.3:更多的選擇性non-covered查詢運行時執行結果

測試一個彙集查詢

咱們最後將一個聚合查詢樣例查詢; 是一個查詢,涉及計算,總計平均等等。 在這種狀況下,它是一個查詢,告訴咱們名字的範圍內重複聯繫表。

結果,在某種程度上,是這樣的:

鋼美林1
斯蒂爾瓊1
斯蒂爾勞拉2
斯蒂爾曼Shanay 1
Steen海蒂2
蒂芬妮斯特凡諾1
施泰納Alan 1

查詢執行信息表2.4中能夠看到。

SQL

選擇名,,COUNT(*)「聯繫人
dbo。 聯繫人——Contacts_noindex和執行
——Contacts_index
LastName「Ste %」
集團由名,

沒有索引

與以前的查詢相同。 (由於它是一個表掃描)

與指數

(104行受影響)
「Contacts_index」。 掃描數1,邏輯讀4

指數的影響

568年讀到4IO減小。

評論

所需的全部信息的查詢索引; 是在理想的指數序列計算數量。 全部的姓始於Ste」條目中連續指數; 和組內,一個姓/名值的全部條目被組合在一塊兒。

不須要訪問的表; 也不是任何排序所需的中間結果。 再次,索引,查詢是一件好事。

2.4:當運行覆蓋聚合查詢執行結果

測試一個Non-Covered聚合查詢

若是咱們改變查詢包括列索引,咱們獲得了性能結果見表2.5

SQL

選擇LastNameFirstName MiddleName,COUNT(*)「聯繫人
dbo。 聯繫人——Contacts_noindex和執行
——Contacts_index
LastName「Ste %」
MiddleName GROUP BY,

沒有索引

與以前的查詢相同。 (由於它是一個表掃描)

與指數

(105行受影響)
「ContactLarge」。 掃描數1,邏輯讀111

指數的影響

IO減小從568年讀111; 之前同樣non-covered查詢

評論

中間工做處理查詢時並不老是出如今統計數據。 技術,使用內存或tempdb排序和合並數據的例子。 在現實中,索引的好處可能大於所示的統計信息。

2.5:noncovered聚合查詢運行時執行結果

結論

咱們如今知道非彙集索引具備如下特性。 非彙集索引:

  • 是一組分類的條目。
  • 基本表的每一行有一個條目。
  • 包含一個索引鍵和一個書籤。
  • 是由你。
  • 是由SQL服務器。
  • 使用SQL Server來最小化所需的努力知足客戶的要求。

和咱們看到的例子中,SQL Server從索引就能夠知足要求; 和它徹底忽略了指數; 還有一些經常使用的索引和表的組合。 出於這個緣由,咱們關閉二級經過更新語句在一級的開始。

當一個請求到達您的數據庫,SQL Server只有三個可能的方法來訪問數據要求的聲明:

  • 訪問非彙集索引,避免訪問表。 這隻可能在索引中包含的全部數據,對於這個表,被請求的查詢
  • 使用索引鍵(s)來訪問非彙集索引,而後使用所選的書籤(s)來訪問表的單個行。
  • 忽略了非聚簇索引表和掃描請求的行。

通常來講,第一個是理想; 和第二個比第三個。 在即將到來的水平,咱們顯示如何增長您的索引的機率將覆蓋你的熱門查詢,以及如何肯定你non-covered足夠選擇性受益於您的索引查詢。 但這將須要更多的詳細信息索引的內部結構比咱們尚未。
才能達到這一點,咱們須要引入其餘類型的SQL Server指數; 彙集索引。 這是三級的主題。

下載代碼

 

資源:

二級- NonClustered.sql|Level2_MillionRowContactTable.sql

這篇文章的一部分SQL Server的階梯索引樓梯

相關文章
相關標籤/搜索