SQL Server 內存優化表的索引設計

測試的版本:SQL Server 2017html

內存優化表上能夠建立哈希索引(Hash Index)和內存優化非彙集(NONCLUSTERED)索引,這兩種類型的索引也是內存優化的,稱做內存優化索引,和基於硬盤的傳統索引有很大的區別:sql

  • 索引結構存儲在內存中,沒有索引碎片和填充因子
  • 對索引所做的更新不會寫入事務日誌文件,這致使索引的更新操做性能很是高

一,建立內存優化索引

在建立內存優化表的索引時,第一種方式是在建立表時定義索引,第二種方式是先建立內存優化表,而後經過alter table命令修改表結構,向表中添加索引,而表級別的索引語法以下所示:數組

<table_index> ::= INDEX index_name { [ NONCLUSTERED ] HASH (column [ ,... n ] ) WITH (BUCKET_COUNT = bucket_count) | [ NONCLUSTERED ] (column [ ASC | DESC ] [ ,... n ] ) [ ON filegroup_name | default ] }

舉個例子,修改表結構,向表中添加哈希索引,在定義索引時必須設置bucket_count的數量:緩存

ALTER TABLE table_name ADD INDEX idx_hash_index_name HASH (index_key) WITH (BUCKET_COUNT = 64);

二,內存優化索引的性能優化

內存優化索引適用的場景是:性能優化

  • 非彙集索引   若是查詢中包含order by子句、或者包含 where index_column > value等範圍掃描操做 ,推薦使用非彙集索引。
  • 哈希索引       若是查詢中包含點查找(point lookup),例如 where index_column = value,而不是範圍掃描,推薦使用哈希索引。

1,哈希索引性能優化app

哈希索引是指SQL Server引擎應用哈希函數F(x),把索引鍵值(Index Key)轉換爲哈希表(哈希索引)。當哈希值相同,而索引鍵不一樣時,稱做產生一個哈希衝突。把哈希值相同的索引鍵連接在一塊兒,組成一個鏈式結構(chain),也稱做衝突鏈。在查找時,須要遍歷衝突鏈來查找數據,所以,衝突鏈變長,會下降哈希查找的性能。ide

哈希衝突是不可避免的,如下兩種狀況,會產生較多的哈希衝突:函數

  • 若是索引鍵存在大量的重複值,
  • 當hashbucket的數量較少時

這兩種狀況致使哈希衝突鏈變長,下降哈希查找的性能,用戶能夠經過下降索引鍵的重複值、增長hashbucket的數量來減小哈希衝突。性能

哈希索引只能點查找(point lookup),而且要求在where子句中應用index key的全部字段、等值條件和與邏輯,例如,哈希索引鍵是colA和colB,在where子句中必須知足:同時出現全部索引鍵、等值條件和與邏輯,也就是:where colA= value1 and colB=value2,只有這樣,才能使用哈希索引進行點查找,不然沒法應用哈希索引。測試

2,內存優化非彙集索引的優化

內存優化非彙集索引的結構是Bw-Tree,在結構上相似於B-Tree結構,具備樹形結構、鍵值是有序的等特色。

從性能上來看,Bw-Tree索引有三個主要特色:

  • 經過無鎖(Lock-Free)的方式來操做Bw-Tree樹,提高了隨機讀和範圍讀的性能。
    • 索引按照前序字段進行排序,在查找時,索引鍵的前序字段很是重要,前序字段必須出如今where/on 子句的條件斷言中。
    • 適合範圍查找,只適用於按照索引定義的排序方向的查找,而不能用於逆向排序的查找
  • 經過Log-Structed Storage方式寫數據,傳統的checkpoint寫數據的方式是隨機寫,而Log-Structed Storage是順序寫,提升寫操做的性能。
  • 對數據的更新採用Delta Update方式,提升了緩存的命中率。

Bw-Tree結構的索引,和普通的B-Tree結構相比,讀寫性能提升,解決了高性能讀和寫不能兼得的問題。

三,內存優化的非彙集索引的結構特色

內存非彙集索引相似於B-Tree結構,稱做Bw-Tree。從總體上看,Bw-Tree是按照Page ID組織的頁面映射。

在Bw-Tree結構中,每一個索引Page具備一組有序鍵值(該結構相似於普通的B樹),鍵值是按照大小順序排列的,而且索引中包含層次結構,父級別指向子級別,葉級別指向數據行。

差別是Bw-Tree能夠把多個數據行鏈接在一塊兒,索引結構中的頁面指針是邏輯頁面的ID,這個邏輯頁面的ID其實是頁面映射表的偏移量,該映射表具備每一個頁面的物理地址,經過偏移量找到每一個頁面在內存中實際的物理地址。

在非葉子級別中,父級別的頁面中存儲的鍵值是它指向的子級頁面中的鍵值的最大值,而且每一行還包含該頁面邏輯頁ID(偏移量)。葉級數據頁不只包含鍵值,還包含頁面的物理地址。

Bw-Tree結構大體以下圖所示:有相似B-Tree的樹形結構(存儲的數據和索引)和Mapping Table(存儲邏輯頁面ID和物理地址的映射)。

在內存非彙集索引中,沒有索引頁的就地更新(in-place update),爲了實現該目的,引入了新的更新機制:

  • 在更新頁時,不須要latch 和lock
  • 索引頁不是固定的大小

Bw-Tree結構解決了B-tree高性能讀和寫不能兼得的問題,可能會存在性能抖動。

四,哈希索引的結構特色

哈希索引包含一個由指針構成的數組,數組中的每一個元組叫作一個hash bucket:

  • 每一個hash bucket佔用8Bytes,用於指向key entry構成的鏈式列表
  • 每一個entry主要由索引鍵的值、對應的數據行的地址和指向下一個entry的指針構成
  • 每一個entry有一個指針,用於指向鏈中下一個entry,經過這種方式,entry構成鏈式結構

哈希索引的結構,以下圖所示,左側是哈希表,右側上一是表數據(Name、City)+時間戳+索引指針,右側中下的兩行是表數據,中間經過Index prt連接爲一個chain。

hash bucket的數量必須在索引定義時指定:

  • 哈希索引的hash bucket的最大數量是 1,073,741,824
  • 較短的鏈式列表比較長的鏈式列表性能更好
  • hash bucket的數量與表中惟一值的數量的比值越低,每一個hash bucket指向的鏈式列表的長度越長,性能越差。所以,應該適當增長hash bucket的數量。
  • 理想狀況下,hash bucket最好是表中惟一值數量的1到2倍。

 

參考文檔:

Index Architecture & Design

關於Bw-Tree結構的兩個Paper

原文出處:https://www.cnblogs.com/ljhdo/p/10533688.html

相關文章
相關標籤/搜索