許多查詢只涉及文件中的少量記錄,如查詢ID為22201的學生的總分數,如果系統讀取每一個元組並檢查,這樣的操作方式是低效的。理想情況下,需要系統能夠直接定位記錄,為了支持這樣的訪問方式,我們設計了與文件相關的數據結構-索引。
基本概念
有兩種基本的索引類型
- 順序索引(Ordered Indices):基於值的順序排序。
- 哈希索引(Hash Indices):基於值在一系列桶中的均勻分布,值屬於哪個散列桶由哈希函數決定。
對於不同的索引技術,必須基於以下幾種因素:
- 訪問類型(Access types):能有效支持的訪問類型,包括訪問具有特定屬性或者屬性值落在某個范圍的記錄。
- 訪問時間(Access time):查詢中訪問數據項或項集所需要的時間。
- 插入時間(Insert time):插入新數據項的時間,包括找到正確的位置插入數據項和更新索引所需要的時間。
- 刪除時間(Delete time):刪除數據項的時間,包括找到要被刪除的項和更新索引所需要的時間。
- 空間開銷(Space overhead):索引結構所占據的額外空間。
我們將用於查找記錄的屬性或屬性集稱為搜索碼(search key)
順序索引
聚集索引(clustering index):記錄在文件中的物理順序與搜索碼的順序一致,也稱為主索引(primary index),聚集索引的搜索碼常常是主碼,但並非總是如此。
非聚集索引(nonclustering index)或輔助索引(secondary index):搜索碼的順序與文件記錄的順序不同。
一般而言,一個表中只有一個聚集索引。
稠密索引和稀疏索引
索引項(index entry)由一個搜索碼和指向該搜索碼的一條或多條指針構成。
- 稠密索引(dense index):每個搜索碼值都有一個索引項。
- 稀疏索引(sprase index):只為某些搜索碼具有索引項,只有當關系按照搜索碼一致的順序排列時才能使用稀疏索引,換句話說,只有索引是聚集索引才能使用稀疏索引,為了定位一條記錄,我們找到小於等於搜索碼值的最大的索引項,然后從該索引項開始順序往下查找。
如圖,在稠密索引中查找22222可直接通過索引項的指針找到,在稀疏索引中,需要先找到10101,然后根據其索引項的指針順序往下查找。
稠密索引通常比稀疏索引查找的更快,但稀疏索引所占空間小,插入刪除的開銷也小。
折中:對於每個塊可以建立一個稀疏索引,數據庫的查詢時間主要由塊從磁盤到內存的時間決定,塊在內存中查找時間與之相比是可以忽略的。
多級索引
對於10000個塊(假定一個塊4KB)的索引,如果采用二分法,需要讀取14次,讀一塊平均耗時10ms,該搜索將耗時140ms,意味着每秒中只能進行7次索引搜索。
為了處理這個問題,在原始的索引上加了一個外層的稀疏索引。
10000個內層索引塊需要10000個外層索引項,也就是100塊,假設外層索引已經在內存中,則一次查詢只需要讀一個索引塊,不需要使用二分法,因此每秒鍾可以執行14次索引查找。如果二級索引仍然很大,可以再加一層成為三級索引,以此類推。
索引的更新
單級索引的更新
- 插入
- 稠密索引
- 不在索引中就插入合適的位置。
- 在索引中,如果索引項存儲的是同一搜索碼所有記錄的指針,則系統增加一個指向新紀錄的指針,否則,索引項僅存儲第一條記錄的指針,將帶插入的記錄放在其他記錄之后。
- 稀疏索引
- 將新塊的第一個搜索碼值插入到索引中,如果新插入的塊中有最小搜索碼值,系統更新指向該塊的索引,否則,不做任何改動。
- 刪除
- 稠密索引
- 如果刪除的是該搜索碼的唯一一條記錄,系統從索引中刪除對應的索引項。
- 如果索引項存儲的是指向所有具有搜索碼的指針,則從索引項中刪除指向被刪除記錄的指針。
- 如果索引項存儲的是指向該搜索碼的第一條記錄的指針,如果被刪除的是第一條記錄的指針,則更新索引項,使其指向下一條。
- 稀疏索引
- 如果不包含該搜索碼的索引項,則不修改索引。
- 否則,如果是唯一一條記錄,則用下一個搜索碼值替換該索引項,如果下一個有索引項,則直接刪除。
- 如果不是唯一記錄,則索引項更新為相同搜索碼值的下一條記錄。