實(shí)現(xiàn)SQL Server 索引底層與操作中的注意事項(xiàng)
本文主要介紹的是SQL Server 索引底層的實(shí)現(xiàn),以及對(duì)索引結(jié)構(gòu)的具體描述,非聚集索引的描述,以及對(duì)非聚集索引在實(shí)際操作中要注意的相關(guān)事項(xiàng)的具體描述,以下就是文章的相關(guān)問題的描述。
頁(yè)和盤區(qū)(Page and Extents)
你的表(Tables)中數(shù)據(jù)實(shí)際上都存儲(chǔ)在頁(yè)(pages)里,除了BLOB類型的數(shù)據(jù)。如果某列的字段的類型為BLOB那么將有一個(gè)16字節(jié)的指針指向BLOB page。頁(yè)是MS SQL Server中數(shù)據(jù)存儲(chǔ)的最小單位。
每頁(yè)包含以行(row)為單位保存數(shù)據(jù)。一行只能存儲(chǔ)在一個(gè)頁(yè)中。每頁(yè)可以容納8KB的信息。因?yàn)檫@個(gè)原因,每行的***值為8KB。一組相鄰的8個(gè)頁(yè)被稱為一個(gè)盤區(qū)(Extent)
堆文件和分配映射索引(Heap and the Index Allocation Map(IAM))
堆文件在sysindexs表中只有一行記錄,并且其indid = 0. sysindexs.FIRSTIAM字段指向了IAM頁(yè)鏈表中一個(gè)IAM頁(yè),IAM頁(yè)是用來管理SQL Server已經(jīng)給堆文件分配的空間。MS SQL Server2000用IAM(Index Allocation Map)頁(yè)來在堆文件中導(dǎo)航(navigate)。在堆文件中,數(shù)據(jù)頁(yè)(data page)和數(shù)據(jù)頁(yè)中數(shù)據(jù)沒有按照特定的順序存儲(chǔ),也沒有鏈接在一起。數(shù)據(jù)頁(yè)之間唯一的邏輯鏈接是通過IAM頁(yè)中記錄來實(shí)現(xiàn)的。
索引結(jié)構(gòu)(Index Structure)
所有的SQL Server 索引都是 B-Trees。在這種樹的頂端有一個(gè)根頁(yè)(root page),通過root page來訪問N個(gè)中級(jí)(intermediate level)頁(yè),直到樹的底部、或葉級(jí)(leaf level)??梢酝ㄟ^樹中每個(gè)節(jié)點(diǎn)的指針從上向下掃描整個(gè)索引樹。另外,每個(gè)SQL Server 索引級(jí)(index leves)(可能是intermediate leve or leaf level)都有一個(gè)頁(yè)鏈(page chain)。
在一個(gè)索引中有許多intermediate level。索引樹的級(jí)數(shù)(樹的高度)與索引碼的寬度、索引類型、記錄行數(shù)和表中的頁(yè)數(shù)有關(guān),并且索引樹的級(jí)數(shù)是影響索引性能的一個(gè)重要參數(shù)。
非聚集索引(Nonclustered Indexs)
一個(gè)非聚集索引與一本書的索引相似。數(shù)據(jù)存儲(chǔ)在一個(gè)地方,索引存儲(chǔ)在另外一個(gè)地方,可以通過索引中的指針來訪問存儲(chǔ)的數(shù)據(jù)。索引中的條目是按照索引碼的值按序存儲(chǔ),但是表中的信息可以按照不同的順序存儲(chǔ)(如可以按照聚集索引存儲(chǔ))。如果表中沒有創(chuàng)建聚集索引,那么表中的記錄就不能保證按照某種特定的順序。
與你用一本書的索引方式一樣,SQL Server2000也是先通過非聚集索引檢索到查找數(shù)據(jù)在表的位置,然后通過該位置來檢索數(shù)據(jù)。這使得非聚集索引非常適合精確匹配查詢(This makes nonclustered indexes the optimal choice for exact match queries),因?yàn)樗饕龡l目中包含了你需要查找數(shù)據(jù)的位置信息。
如果當(dāng)前的表是以聚集索引方式存儲(chǔ),那么非聚集索引的位置信息就是聚集索引的索引碼(index key);否則,位置信息就是row ID(RID),每個(gè)RID由file number、page number和 slot number of row(每行記錄的槽號(hào))。比如,要在一個(gè)表中檢索某個(gè)employee ID(emp_id),該表已經(jīng)有在emp_id列上創(chuàng)建了非聚集SQL Server 索引,SQL Server查找索引樹,找到一個(gè)索引條目包含你需要查找的emp_id,然后利用其中RID來訪問到對(duì)應(yīng)數(shù)據(jù)頁(yè)中的值。
注意事項(xiàng)
非聚集索引適用于以下場(chǎng)景:
列中包含大量的不同值,如last name 和 first name 構(gòu)成的復(fù)合索引(假如已用另外列創(chuàng)建的聚集索引) 。如果某列中只有很少的不同值,如0或者1,大多數(shù)查詢不會(huì)利用該索引的,因?yàn)橐粋€(gè)表掃描通常更有效率。
不返回大量結(jié)果集的查詢 Queries that not return large result sets
經(jīng)常被包含在一個(gè)查詢條件語(yǔ)句(WHERE clause)的列,且該查詢返回精確配備(return exact matches)
決策支持系統(tǒng)中經(jīng)常需要表之間的關(guān)聯(lián)(join)和聚集(group)。在被包含在join和grouping操作的列上建立非聚集索引,和在外鍵列上建立聚集索引。
一個(gè)給定的查詢包含了表中所有的列,這樣可以減少對(duì)表或聚集SQL Server 索引的訪問。(Covering all columns from one table in a given query. This eliminates accessing the table or clustered index altogether.)我的理解就是覆蓋索引。
聚集索引(Clustered Indexs)
一個(gè)聚集索引決定了一個(gè)表中數(shù)據(jù)的物理存儲(chǔ)順序。一個(gè)聚集索引與一個(gè)電話目錄相似,電話目錄是按照l(shuí)ast name來存放。因?yàn)榫奂饕龥Q定一張表中數(shù)據(jù)的物理存放順序,所以一張表只能有個(gè)聚集索引,一個(gè)聚集索引可以包含多個(gè)列(復(fù)合索引),就像電話目錄一樣按照l(shuí)ast name 和 first name記錄一樣,聚集索引與Oracle中的IOT'S(Index-Organized Tables)相似。
一個(gè)聚集索引對(duì)范圍查詢非常有效率efficient on columns that are often searched for ranges of values。當(dāng)用聚集索引把***個(gè)行檢索出來之后,后續(xù)行一定能保證在物理上是相鄰的。例如,應(yīng)用的某個(gè)查詢需要頻繁執(zhí)行一個(gè)范圍查詢,聚集索引可以快速定位到滿足條件的***個(gè)數(shù)據(jù),然后再檢索表中與之相鄰的記錄直到***一條記錄。
這樣可以調(diào)高這類查詢的性能。另外,如果某列經(jīng)常用來對(duì)表中的數(shù)據(jù)進(jìn)行排序(sort),該情況下也可利用聚集SQL Server 索引來節(jié)省每次排序的時(shí)間。
當(dāng)索引值唯一時(shí),需要查找一個(gè)指定行,此時(shí)聚集索引也是高效率的。例如,用最快的方式來找到一個(gè)指定empoyee ID的employee記錄就是在emp_id列上創(chuàng)建一個(gè)聚集索引。
注意事項(xiàng)
在創(chuàng)建聚集索引時(shí),SQL Server 索引列應(yīng)該盡量少,這一點(diǎn)很重要。如果定義一個(gè)大的索引碼,那么該表中的任何非聚集索引就會(huì)顯著的增大,因?yàn)槊總€(gè)非聚集索引葉級(jí)索引條目都包含了一個(gè)聚集索引碼。
聚集SQL Server 索引適用于以下場(chǎng)景:
列中包含大量的不同值
返回一個(gè)范圍記錄的查詢,像BETWEEN, >, >=, <, and <=.的操作;
順序訪問的列
返回大量記錄的查詢
在查詢中某列被頻繁的包含在join或group語(yǔ)句中,尤其該列也是該表的外鍵。在ORDER BY或 GROUP BY語(yǔ)句的列上建立聚集索引可以減少SQL Server對(duì)數(shù)據(jù)的排序,因?yàn)楸碇行幸呀?jīng)是有序的了,這樣可提高查詢的性能。
在OLTP類的應(yīng)用中經(jīng)常需要快速查找某行記錄,尤其是一主鍵的來查找,此時(shí)可在主鍵上創(chuàng)建一個(gè)聚集索引。
聚集索引不適合以下場(chǎng)景:
頻繁變化的列。這樣造成了表中行經(jīng)常移動(dòng),
寬鍵(wide keys)聚集索引的SQL Server 索引碼被所有的非聚集索引來用來檢索,所被存儲(chǔ)在每個(gè)非聚集索引的葉級(jí)索引條目中。
【編輯推薦】