[摘要]索引是影響關系數據庫(RDBMS)性能的重要因素之一。當今常用的關系數據庫,如SQL Server、Sybase、Oracle、DB2、informix等,為了提高性能,都提供相應的索引機制。本文介紹了索引的概念、使用方法以及日常維護。
[關鍵詞]數據庫 索引 檢索
一、索引的概念
1.索引基本概念
索引是一個單獨的、物理的數據庫結構,它是某個表中一列或若干列值的集合和相應的指向表中物理標識這些值的數據頁的邏輯指針清單。表的存儲由兩部分組成,一部分用來存放數據頁面,另一部分存放索引頁面。通常,索引頁面相對于數據頁面來說小得多。數據檢索花費的大部分開銷是磁盤讀寫,沒有索引就需要從磁盤上讀表的每一個數據頁,如果有索引,則只需查找索引頁面就可以了。所以建立合理的索引,就能加速數據的檢索過程。
2.索引分類
根據索引的順序與數據表的物理順序是否相同可以分為:聚簇索引(clustered index)和非聚簇索引(nonclustered index)。
(1)聚簇索引重新組織表中的數據以按指定的一個或多個列的值排序。聚簇索引的葉節點包含實際的數據,因此用它查找數據很快,但每個表只能建一個聚簇索引。
(2)非聚簇索引不重新組織表中的數據,它的葉節點中存儲了組成非聚簇索引的列的值和行定位指針。
下面,我們舉例來說明一下聚集索引和非聚集索引的區別:
漢語字典的正文本身就是一個聚簇索引。比如,我們要查“安”字,就會很自然地翻開字典的前幾頁,因為“安”的拼音是“an”,而按照拼音排序漢字的字典是以英文字母“a”開頭并以“z”結尾的,那么“安”字就自然地排在字典的前部。如果您翻完了所有以“a”開頭的部分仍然找不到這個字,那么就說明您的字典中沒有這個字;也就是說,字典的正文部分本身就是一個目錄,您不需要再去查其他目錄來找到您需要找的內容。
我們把這種正文內容本身就是一種按照一定規則排列的目錄稱為“聚簇索引”。
如果您認識某個字,您可以快速地從自動中查到這個字。但您也可能會遇到您不認識的字,不知道它的發音,這時候,您就不能按照剛才的方法找到您要查的字,而需要去根據“偏旁部首”查到您要找的字,然后根據這個字后的頁碼直接翻到某頁來找到您要找的字。但您結合“部首目錄”和“檢字表”而查到的字的排序并不是真正的正文的排序方法。
我們把這種目錄純粹是目錄,正文純粹是正文的排序方式稱為“非聚簇索引”。通過以上例子,我們可以理解到什么是“聚簇索引”和“非聚簇索引”。
二、索引的使用
1.聚簇索引的使用
在聚簇索引下,數據在物理上按順序排在數據頁上,重復值也排在一起,因而在那些包含范圍檢查(between、<、<=、>、>=)或使用group by、order by的查詢時,一旦找到具有范圍中第一個鍵值的行,具有后續索引值的行必然連在一起,不必進一步搜索,避免了大范圍掃描,可以大大提高查詢速度。
2.非聚簇索引的使用
非聚簇索引的葉節點不包含實際的數據,因此它檢索效率較低,一個表只能建一個聚簇索引,當用戶需要建立多個索引時就需要使用非聚簇索引了。在建立非聚簇索引時,要權衡索引對查詢速度的加快與降低修改速度之間的利弊。
3.索引使用的誤區
(1)主鍵就是聚簇索引
一些數據庫系統(比如SQL server)會把主鍵默認為聚簇索引,這種做法常常造成聚簇索引的浪費。通常,我們會為每個表建立一個ID列,以區分每條數據,并且該列是自動增大的,步長一般為1。如果我們把這個列設為聚簇索引。這樣做可以使數據在數據庫中按ID進行物理排序,但這種做法在實際應用中意義并不大。
舉例如下:以電信級數據庫中存儲話單的表為例,我們查詢某個用戶的通話記錄時經常需要返回某個時間特定范圍內的數據。下面我們分幾種情況觀察在不同索引條件下查詢相同內容所用的時間。
假設話單表名為“rec”,其中主叫號碼字段名為“callingnumber”,日期字段名為“date”,要求是從表rec中檢索callingnumber為“037112345678”的主叫號碼2007年3月1日到20日的通話記錄,對應的SQL語句如下:
Select * from rec where date>='20070301' and date<='20070320'and callingnumber='037112345678';
第一種情況,用ID列建立聚簇索引,不為date和callingnumber建立索引,查詢時間為287秒。(相當于整表掃描,此種情況下數據庫的效率是極低的)
第二種情況,用ID列建立聚簇索引,為date和callingnumber(date在前)兩列建立非聚簇索引,查詢時間為83秒。
第三種情況,用date和callingnumber(date在前)列建立聚簇索引,用建立非聚簇索引查詢時間為2秒。
由以上分析可以看出聚簇索引是非常寶貴的,應該為經常用于檢索某個范圍內數據的列或group by、order by等子句的列建立聚簇索引,這樣能夠極大的提高系統性能。
(2)重視以多個列創建的索引中列的順序問題
一些用戶認為只要合理的選擇列建立索引,不必關心列的順序就可以提高檢索速度,這種觀點是錯誤的。多列索引中列的先后順序應該和實際應用中where、group by或order by等子句里列的放置位置相同。參考上面舉的例子,第三種情況下,如果把callingnumber放在date前面,執行上述SQL語句就不會用到這兩個索引,檢索的時間也會變得很長。
(3)只要建立索引就能顯著提高查詢速度
事實上,我們可以發現上面的例子中,第二、三中情況下建立索引的字段完全相同;不同的僅是前者在date、callingnumber字段上建立的是非聚簇索引,后者在此字段上建立的是聚簇索引,但查詢速度卻有著天壤之別。所以,并非是在任何字段上簡單地建立索引就能提高查詢速度。
三、索引的維護
數據庫系統運行一段時間后,隨著數據行的插入、刪除和數據頁的分裂,索引對系統的優化性能就會大大降低。這時候,我們需要對索引進行統計更新。
下面以informix數據庫為例,對統計更新的概念進行闡述:
為了提高數據庫的效率,INFORMIX提供了一個基于成本的查詢優化器,執行update statistics語句(即統計更新語句)的作用就是將您創建的數據庫表的有關統計信息更新到系統sysmaster的相關表中(如systables、syscolumns、sysindexes、sysdistrib、sysprocplan等),以便查詢優化器選擇最佳的執行路徑。
四、總結
索引有助于提高檢索性能,但過多或不當的索引也會導致系統低效。因為用戶在表中每加進一個索引,數據庫就要做更多的工作。過多的索引甚至會導致索引碎片。
所以說,我們要建立一個“適當”的索引體系,特別是對聚合索引的創建,更應精益求精,以使您的數據庫能得到高性能的發揮。
(作者單位:河南鄭州旅游職業學院)