資料結構與演算法24-線性索引查詢
線性索引查詢
有此資料集可能增長非常快,例如,某些微博網站或大型論壇的帖子和回覆總數每天都是成百萬上千萬條,或者一些伺服器的日誌資訊記錄也可能是海量資料,要保證記錄全部是按照當中的某個關鍵字有序,其時間代價是非常高昂的,所以這種資料都是按先後順序儲存的。
對於這樣的查詢表,我們如何能夠快速 查詢到需要的資料呢?辦法就是----索引
索引是 了加快查詢速度而設計的一種資料結構。
索引就是把一個關鍵字與它對應的記錄相關聯的過程,一個索引由若干個索引項構成,每個索引項至少應包含關鍵字和其對應的記錄在儲存器中的位置等資訊。
索引按照結構可以分為線性索引、樹形索引和多級索引。我們這裡就只介紹線性索引技術。所謂線性索引就是將索引項集合組織為線性結構,也稱為索引表
稠密索引
它是指線性索引中,將資料集中的每個記錄對應一個索引項。
對於稠密索引這個索引表來說,索引一定是按照關鍵碼有序排列的。
索引項有序也就意味著,我們要查詢關鍵字時,可以用到折半、插值、斐波那契等有序查詢演算法,大大提高效率。
比如查詢上表中的18。如果不用索引表,需要6次。而用左側的索引表,折半兩次就可以找到18對應的指標。
這顯然是稠密索引優點,但是如果資料集非常大,比如上億,那也就意味著索引也得同樣的資料集長度規模,對於記憶體有限的計算機來說,可能就需要反覆去訪問磁碟,查詢效能反而大大下降了。
分塊索引
稠密索引因為索引項與資料集的記錄個數相同,所以空間代價很大。為了減少索引的個數,我們可以對資料集進行分塊,使其分塊有序,然後再對每一塊建立一個索引項,從而減少索引項的個數。
分塊有序,是把資料集的記錄分成若干塊,並且這些塊需要滿足兩個條件:
l 塊內無序,即每一塊內的記錄不要求有序。當然,你如果能夠讓塊內有序對查詢來說更理想,不過這就要付出大量時間和空間代價,因此通常我們不要求塊內有序
l 塊間有序,例如要求第二塊所有記錄的關鍵字均要大於第一塊中所有記錄的關鍵字,第三塊的所有記錄的關鍵字均要大於第二塊的所有記錄關鍵字….因為只有塊間有序,才有可能在查詢時帶來效率。
對於分塊有序的資料集,將每塊對應一個索引項,這種索引方法叫做分場索引。我們定義的分塊索引項結構分三個資料項:
n 最大關鍵碼:它儲存每一塊中的最大關鍵字,這樣的好處就是可以使得在它之後的下一塊中最小關鍵字也能比這一塊最大的關鍵字要大
n 儲存了塊中的記錄個數,以便於迴圈時使用
n 用於指向塊首資料元素的指標,便於開始對這一塊中的記錄進行遍歷。
分塊索引是分兩步進行:
1. 在分塊索引表中查詢要查關鍵字所在的塊。由於分塊索引表是塊間有序的,因此很容易利用折半、插值等演算法得到結果。
2. 根據塊首指標找到相應的塊,並在塊中順序查詢關鍵碼。因為塊中可以是無序的,因此只能順序查獲。
倒排索引
搜尋引擎,無論你查詢什麼 樣的資訊,它都可以在極短的時間內給你一些結果,是什麼演算法技術達到這樣的高效查詢呢?
這裡介紹一種最基礎的搜尋技術----倒排索引。
我們來看一個例子:
如下假設有兩篇文章:
1. Books and friends should be few but good .
2. A good book is a good friend.
假設我們忽略掉如“books”,“friends”中的複數”s”以及如“A”這樣的大小寫差異。我們可以整理出這樣一張單詞表,如下圖,並將單詞做了排序,也就是表格顯示了每個不同的單詞分別出現在哪篇文章中,比如“good”它在兩篇文章中都有出現,而is只有在文章2中才有。
在這裡這張單詞表就是索引表,索引項的通用結構是:
1. 次關鍵碼
2. 記錄號表
其中記錄號表儲存具有相同次字關鍵字的所有記錄的記錄號(可以指向記錄的指標或者是該記錄的主關鍵字)。這樣的索引方法就是倒排索引(inverted index)