SqlServer索引的原理與應用

索引的概念

索引的用途:咱們對數據查詢及處理速度已成爲衡量應用系統成敗的標準,而採用索引來加快數據處理速度一般是最廣泛採用的優化方法。算法

索引是什麼:數據庫中的索引相似於一本書的目錄,在一本書中使用目錄能夠快速找到你想要的信息,而不須要讀徹底書。在數據庫中,數據庫程序使用索引能夠重啊到表中的數據,而沒必要掃描整個表。書中的目錄是一個字詞以及各字詞所在的頁碼列表,數據庫中的索引是表中的值以及各值存儲位置的列表。sql

索引的利弊:查詢執行的大部分開銷是I/O,使用索引提升性能的一個主要目標是避免全表掃描,由於全表掃描須要從磁盤上讀取表的每個數據頁,若是有索引指向數據值,則查詢只須要讀少數次的磁盤就行啦。因此合理的使用索引能加速數據的查詢。可是索引並不老是提升系統的性能,帶索引的表須要在數據庫中佔用更多的存儲空間,一樣用來增刪數據的命令運行時間以及維護索引所需的處理時間會更長。因此咱們要合理使用索引,及時更新去除次優索引。數據庫

數據表的基本結構

一個新表被建立之時,系統將在磁盤中分配一段以8K爲單位的連續空間,當字段的值從內存寫入磁盤時,就在這一既定空間隨機保存,當一個 8K用完的時候,數據庫指針會自動分配一個8K的空間。這裏,每一個8K空間被稱爲一個數據頁(Page),又名頁面或數據頁面,並分配從0-7的頁號, 每一個文件的第0頁記錄引導信息,叫文件頭(File header);每8個數據頁(64K)的組合造成擴展區(Extent),稱爲擴展。所有數據頁的組合造成堆(Heap)。併發

SQLS規定行不能跨越數據頁,因此,每行記錄的最大數據量只能爲8K。這就是char和varchar這兩種字符串類型容量要限制在8K之內的 緣由,存儲超過8K的數據應使用text類型,實際上,text類型的字段值不能直接錄入和保存,它只是存儲一個指針,指向由若干8K的文本數據頁所組成 的擴展區,真正的數據正是放在這些數據頁中。 高併發

頁面有空間頁面和數據頁面之分。  sqlserver

當一個擴展區的8個數據頁中既包含了空間頁面又包括了數據或索引頁面時,稱爲混合擴展(Mixed Extent),每張表都以混合擴展開始;反之,稱爲一致擴展(Uniform Extent),專門保存數據及索引信息。 性能

表被建立之時,SQLS在混合擴展中爲其分配至少一個數據頁面,隨着數據量的增加,SQLS可即時在混合擴展中分配出7個頁面,當數據超過8個頁面時,則從一致擴展中分配數據頁面。  大數據

空間頁面專門負責數據空間的分配和管理,包括:PFS頁面(Page free space):記錄一個頁面是否已分配、位於混合擴展仍是一致擴展以及頁面上還有多少可用空間等信息;GAM頁面(Global allocation map)和SGAM頁面(Secodary global allocation map):用來記錄空閒的擴展或含有空閒頁面的混合擴展的位置。SQLS綜合利用這三種類型的頁面文件在必要時爲數據表建立新空間;  優化

數據頁或索引頁則專門保存數據及索引信息,SQLS使用4種類型的數據頁面來管理表或索引:它們是IAM頁、數據頁、文本/圖像頁和索引頁。 spa

在WINDOWS中,咱們對文件執行的每一步操做,在磁盤上的物理位置只有系統(system)才知道;SQL SERVER沿襲了這種工做方式,在插入數據的過程當中,不但每一個字段值在數據頁面中的保存位置是隨機的,並且每一個數據頁面在「堆」中的排列位置也只有系統 (system)才知道。  

這是爲何呢?衆所周知,OS之因此能管理DISK,是由於在系統啓動時首先加載了文件分配表:FAT(File Allocation Table),正是由它管理文件系統並記錄對文件的一切操做,系統才得以正常運行;同理,做爲管理系統級的SQL SERVER,也有這樣一張相似FAT的表存在,它就是索引分佈映像頁:IAM(Index Allocation Map)。  

IAM的存在,使SQLS對數據表的物理管理有了可能。  

IAM頁從混合擴展中分配,記錄了8個初始頁面的位置和該擴展區的位置,每一個IAM頁面能管理512,000個數據頁面,若是數據量太 大,SQLS也能夠增長更多的IAM頁,能夠位於文件的任何位置。第一個IAM頁被稱爲FirstIAM,其中記錄了之後的IAM頁的位置。  

數據頁和文本/圖像頁互反,前者保存非文本/圖像類型的數據,由於它們都不超過8K的容量,後者則只保存超過8K容量的文本或圖像類型數據。而索 引頁顧名思義,保存的是與索引結構相關的數據信息。瞭解頁面的問題有助咱們下一步準確理解SQLS維護索引的方式,如頁拆分、填充因子等。  

頁分裂

一半的數據將保留在老頁面,而另外一半將放入新頁面,而且新頁面可能被分配到任何可用的頁。因此,頻繁頁分裂,後果很嚴重,將使物理表產生大量數據碎片,致使直接形成I/O效率的急劇降低,最後,中止SQLS的運行並重建索引將是咱們的惟一選擇!

填充因子

索引的一個特性,定義該索引每頁上的可用空間量。FILLFACTOR(填充因子)適應之後表數據的擴展並減少了頁拆分的可能性。填充因子是從0到100的百分比數值,設爲100時表示將數據頁填滿。只有當不會對數據進行更改時(例如 只讀表中)才用此設置。值越小則數據頁上的空閒空間越大,這樣能夠減小在索引增加過程當中進行頁分裂的須要,但這一操做須要佔用更多的硬盤空間。填充因子指定不當,會下降數據庫的讀取性能,其下降量與填充因子設置值成反比。

索引的分類

SQL SERVER中有多種索引類型。

按存儲結構區分:「彙集索引(又稱聚類索引,簇集索引)」,「分彙集索引(非聚類索引,非簇集索引)」

按數據惟一性區分:「惟一索引」,「非惟一索引」

按鍵列個數區分:「單列索引」,「多列索引」。

彙集索引

彙集索引是一種對磁盤上實際數據從新組織以按指定的一列或多列值排序。像咱們用到的漢語字典,就是一個彙集索引,好比要查「張」,咱們天然而然就翻到字典的後面百十頁。而後根據字母順序跟查找出來。這裏用到微軟的平衡二叉樹算法,即首先把書翻到大概二分之一的位置,若是要找的頁碼比該頁的頁碼小,就把書向前翻到四分之一處,不然,就把書向後翻到四分之三的地方,依此類推,把書頁續分紅更小的部分,直至正確的頁碼。

因爲彙集索引是給數據排序,不可能有多種排法,因此一個表只能創建一個彙集索引。科學統計創建這樣的索引須要至少至關與該表120%的附加空間,用來存放該表的副本和索引中間頁,可是他的性能幾乎老是比其它索引要快。

因爲在彙集索引下,數據在物理上是按序排列在數據頁上的,重複值也排在一塊兒,於是包含範圍檢查(bentween,<,><=,>=)或使用group by 或order by的查詢時,一旦找到第一個鍵值的行,後面都將是連在一塊兒,沒必要在進一步的搜索,避免啦大範圍的掃描,能夠大大提升查詢速度。

非彙集索引

sqlserver默認狀況下創建的索引是非彙集索引,他不從新組織表中的數據,而是對每一行存儲索引列值並用一個指針指向數據所在的頁面。他像漢語字典中的根據‘偏旁部首’查找要找的字,即使對數據不排序,然而他擁有的目錄更像是目錄,對查取數據的效率也是具備的提高空間,而不須要全表掃描。

一個表能夠擁有多個非彙集索引,每一個非彙集索引根據索引列的不一樣提供不一樣的排序順序。

建立索引

語法

CREATE [UNIQUE] [CLUSTERED| NONCLUSTERED ]
INDEX index_name ON { table | view } ( column [ ASC | DESC ] [ ,...n ] )
[with[PAD_INDEX][[,]FILLFACTOR=fillfactor]
[[,]IGNORE_DUP_KEY]
[[,]DROP_EXISTING]
[[,]STATISTICS_NORECOMPUTE]
[[,]SORT_IN_TEMPDB]
]
[ ON filegroup ]   

CREATE INDEX命令建立索引各參數說明以下:

UNIQUE:用於指定爲表或視圖建立惟一索引,即不容許存在索引值相同的兩行。

CLUSTERED:用於指定建立的索引爲彙集索引。

NONCLUSTERED:用於指定建立的索引爲非彙集索引。

index_name:用於指定所建立的索引的名稱。

table:用於指定建立索引的表的名稱。

view:用於指定建立索引的視圖的名稱。

ASC|DESC:用於指定具體某個索引列的升序或降序排序方向。

Column:用於指定被索引的列。

PAD_INDEX:用於指定索引中間級中每一個頁(節點)上保持開放的空間。

FILLFACTOR = fillfactor:用於指定在建立索引時,每一個索引頁的數據佔索引頁大小的百分比,fillfactor的值爲1到100。

IGNORE_DUP_KEY:用於控制當往包含於一個惟一彙集索引中的列中插入重複數據時SQL Server所做的反應。

DROP_EXISTING:用於指定應刪除並從新建立已命名的先前存在的彙集索引或者非彙集索引。

STATISTICS_NORECOMPUTE:用於指定過時的索引統計不會自動從新計算。

SORT_IN_TEMPDB:用於指定建立索引時的中間排序結果將存儲在 tempdb 數據庫中。

ON filegroup:用於指定存放索引的文件組。

例子:

--表bigdata建立一個名爲idx_mobiel的非彙集索引,索引字段爲mobiel
create index idx_mobiel
on bigdata(mobiel) 


--表bigdata建立一個名爲idx_id的惟一彙集索引,索引字段爲id
--要求成批插入數據時忽略重複值,不從新計算統計信息,填充因子爲40
create unique clustered index idx_id
on bigdata(id) 
with pad_index,
fillfactor=40,
ignore_dup_key,
statistics_norecompute

管理索引

Exec sp_helpindex BigData   --查看索引定義

Exec sp_rename 'BigData.idx_mobiel','idx_big_mobiel'  --將索引名由'idx_mobiel' 改成'idx_big_mobiel'

drop index BigData.idx_big_mobiel  --刪除bigdata表中的idx_big_mobiel索引

dbcc showcontig(bigdata,idx_mobiel) --檢查bigdata表中索引idx_mobiel的碎片信息

dbcc indexdefrag(Test,bigdata,idx_mobiel)  --整理test數據庫中bigdata表的索引idx_mobiel上的碎片

update statistics bigdata  --更新bigdata表中的所有索引的統計信息

索引的設計原則

對於一張表來講索引的有無和創建什麼樣的索引,要取決與where字句和Join表達式中。

通常來講創建索引的原則包括如下內容:

  • 系統通常會給逐漸字段自動創建彙集索引。
  • 有大量重複值且常常有範圍查詢和排序、分組的列,或者常常頻繁訪問的列,考慮創建彙集索引。
  • 在一個常常作插入操做的表中創建索引,應使用fillfactor(填充因子)來減小頁分裂,同時提升併發度下降死鎖的發生。若是在表爲只讀表,填充因子可設爲100.
  • 在選擇索引鍵時,儘量採用小數據類型的列做爲鍵以使每一個索引頁能容納儘量多的索引鍵和指針,經過這種方式,可以使一個查詢必需遍歷的索引頁面下降到最小,此外,儘量的使用整數作爲鍵值,由於整數的訪問速度最快。
相關文章
相關標籤/搜索