順序檔案組織的缺點之一是必須通過通路索引或使用二分法搜尋來定位資料,這需要較多的I/O操作。基于散列技術的檔案組織方式則不需要通路索引結構,散列也提供了一種組織索引的方式。
在散列(hash)技術中,用桶(bucket)來表示能存儲一條或多條記錄的存儲單元。如果K代表所有搜尋碼的集合,B代表所有bucket的集合,則散列函數h表示一個從K到B的映射函數。
插入搜尋碼為Ki的記錄時,通過散列函數計算h(Ki)得出bucket的位址,如果這個bucket還有空間,就将資料插入。
查詢Ki時,也是先通過h(Ki)得出bucket的位址,但bucket中往往有多條記錄,這時就需要進一步根據搜尋碼在bucket内部搜尋。
散列可以有兩種用途,在散列檔案組織中,通過散列函數直接定位記錄所在的磁盤塊;在散列索引組織中,把搜尋碼和指針組織成一個散列檔案結構。
a) 散列函數
合理地選擇散列函數非常重要,否則可能導緻記錄被集中映射到少數幾個bucket的情況。要求散列函數的分布特性是均勻、随機的,既每個bucket被配置設定到的記錄數應該是相等的,而且配置設定結果與搜尋碼本身的順序無關。
典型的散列函數是根據搜尋碼的二進制值進行計算的,比如可以計算二進制所有位的和,然後取模。一個結果良好設計的散列函數應不受記錄數量的影響,而具有穩定的搜尋效率。
b) Bucket溢出的處理
如果記錄被映射到一個Bucket時Bucket以及沒有可用空間,就會發生溢出。溢出的原因可能是因為随着記錄數的增長,沒有足夠的bucket;也可能是因為散列函數設計不合理或者存在太多相同的搜尋碼,導緻記錄被集中映射到某些bucket,而一個bucket能容納的記錄是有限的,這種情況稱為桶偏斜(bucket
skew)。
為了應對bucket溢出,可以在确定bucket數量時留一定的餘量,但這會造成空間浪費;也可以使用溢出桶(overflow
bucket)來接收溢出記錄:一旦發生溢出,就新增一個溢出桶,以接收溢出記錄,溢出桶與原始桶構成連結清單(overflow
chaining),于是查找資料時,要增加對是否存在溢出桶的探查,如果存在,則進一步在溢出桶中搜尋。
這種靜态散列的缺點在于必須在設計階段确定好bucket的數量,随着記錄的數的增加或收縮,bucket數無法跟随變化,會造成溢出或空間浪費。
c) 散列索引
除了散列檔案組織,還可以用散列的方式組織索引。将散列函數作用于搜尋碼以确定對應的桶,然後将此搜尋碼以及相應的指針存入。
學習資料:Database System Concepts, by Abraham Silberschatz, Henry F.Korth, S.Sudarshan