【搜索引擎】搜索引擎索引數據結構和算法

最近一直在研究sphinx的工做機制,在[搜索引擎]Sphinx的介紹和原理探索簡單地介紹了其工做原理以後,還有不少問題沒有弄懂,好比底層的數據結構和算法,因而更進一步地從數據結構層面瞭解其工做原理。在網上搜了不少資料,發現沒有不少介紹這方面的文章,後來找到了一本書,《這就是搜索引擎》,拜讀了本書的第三章,介紹了主流搜索引擎用的數據結構及其工做原理,sphinx使用的數據結構也是同樣的,用的也是倒排索引。算法

注:本文不會對sphinx和搜索引擎嚴格區分開,同一做搜索引擎看待。服務器

先附圖一枚:數據結構

索引基礎

先介紹與搜索引擎有關的一些基本概念,瞭解這些概念對後續瞭解工做機制很是重要。負載均衡

單詞-文檔矩陣

單詞-文檔矩陣是表達二者之間所具備的一種包含關係的概念模型。以下圖所示,每列表明一個文檔,每行表明一個單詞,打對鉤的位置表明包含關係。數據結構和算法

 

從縱向看,能夠得知每列表明文檔包含了哪些單詞;從橫向看,每行表明了哪些文檔包含了某個單詞。搜索引擎的索引其實就是實現單詞-文檔矩陣的具體數據結構。能夠有不一樣的方式來實現上述概念模型,好比倒排索引、簽名文件、後綴樹等方式。但實驗數據代表,倒排索引是單詞到文檔映射關係的最佳實現方式。分佈式

倒排索引基本概念

文檔(Document):以文本形式存在的存儲對象。如:網頁、Word、PDF、XML等不一樣格式的文件。
文檔集合(Document Collection):若干文檔構成的集合。如:大量的網頁。
文檔編號(Document ID):搜索引擎內部,惟一標識文檔的惟一編號。
單詞編號(Word ID):搜索引擎內部,惟一標識單詞的惟一編號。
倒排索引(Inverted Index):實現單詞--文檔矩陣的一種具體存儲形式。倒排索引主要有單詞詞典和倒排文件組成。
單詞詞典(Lexicon):文檔集合中出現過的全部單詞構成的字符串集合,單詞詞典內每條索引項記載單詞自己的一些信息及指向倒排列表的指針。
倒排列表(PostingList):出現了某個單詞的全部文檔的文檔列表及單詞在該文檔中出現的位置信息。列表中每條記錄稱爲一個倒排項(Posting)。
倒排文件(Inverted File):保存全部單詞的倒排列表的文件,倒排文件是存儲倒排索引的物理文件。函數

概念之間的關係如圖:性能

 

倒排索引簡單實例

下面舉一個實例,這樣對倒排索引有一個更直觀的感覺。ui

假設文檔集合包含5個文檔,每一個文檔內容以下圖所示:搜索引擎

 

創建的倒排索引以下圖:

 

 

單詞ID:記錄每一個單詞的單詞編號;

單詞:對應的單詞;

文檔頻率:表明再文檔集合中有多少個文檔包含某個單詞

倒排列表:包含單詞ID及其餘必要信息

TF:單詞在某個文檔中出現的次數

POS:單詞在文檔中出現的位置

以單詞「加盟」爲例,其單詞編號爲8,文檔頻率爲3,表明整個文檔集合中有三個文檔包含這個單詞,對應的倒排列表爲{(2;1;<4>),(3;1;<7>),(5;1;<5>)},含義是在文檔2,3,5出現過這個單詞,在每一個文檔的出現過1次,單詞「加盟」在第一個文檔的POS是4,即文檔的第四個單詞是「加盟」,其餘的相似。

這個倒排索引已是一個很是完備的索引系統,實際搜索系統的索引結構基本如此。

 

單詞詞典

單詞詞典用來維護文檔集合中出現過的全部單詞的相關信息,同時用來記載某個單詞對應的倒排列表在倒排文件中的位置信息。在查詢時到單詞詞典裏查詢,就能得到相應的倒排列表,並以此做爲後序排序的基礎。

 

經常使用數據結構:哈希加鏈表和樹形詞典結構。

哈希加鏈表

下圖是哈希加鏈表詞典結構的示意圖。主體是哈希表,每一個哈希表項保存一個指針,指針指向衝突連表,相同哈希值的單詞造成鏈表結構。

構建過程:
對文檔進行分詞;
對於作好的分詞,利用哈希函數獲取哈希值;
根據哈希值對應的哈希表項找到對應的衝突鏈表;
若是衝突鏈表已經存在該單詞
  不處理
不然
  加入衝突連表

樹形結構

使用B樹或者B+樹的結構。與哈希表不一樣的是,須要字典項能按照大小排序,即便用數字或字符序。
樹形結構中,使用層級查找,中間節點保存必定順序範圍的詞典項目存儲在哪一個子樹中,最底層的葉子節點存儲單詞的地址信息。

倒排列表

倒排列表用來記錄哪些文檔包含了某個單詞。倒排列表由倒排索引項組成,每一個倒排索引項由文檔ID,單詞出現次數TD以及單詞在文檔中哪些位置出現過等信息。包含某單詞的一些列倒排索引項造成了某個單詞對應的倒排列表。下圖是倒排列表示意圖:

 

創建索引

前面介紹了索引結構,那麼,有了數據以後索引是怎麼創建的呢?主要有三種創建索引的方法。

兩遍文檔遍歷法(2-Pass In-Memory Inversion)

此方法在內存裏完成索引的建立過程。要求內存要足夠大。
第一遍
收集一些全局的統計信息。包括文檔集合包含的文檔個數N,文檔集合內所包含的不一樣單詞個數M,每一個單詞在多少個文檔中出現過的信息DF。
將全部單詞對應的DF值所有相加,就能夠知道創建最終索引所需的內存大小是多少。
獲取信息後,根據統計信息分配內存等資源,同事創建好單詞相對應倒排列表在內存中的位置信息。

第二遍
逐個單詞創建倒排列表信息。得到包含某個單詞的每一個文檔的文檔ID,以及這個單詞在文檔中的出現次數TF,而後不斷填充第一遍掃描時所分配的內存。當第二遍掃描結束的時候,分配的內存正好被填充滿,每一個單詞用指針所指向的內存區域「片斷」,其起始位置和終止位置之間的數據就是這個單詞對應的倒排列表。

排序法(Sort-based Inversion)

在創建索引過程當中,始終在內存中分配固定大小的空間,用來存放詞典信息和索引的中間結果,當分配的空間被消耗光的時候,把中間結果寫入磁盤,清空內存裏中間結果所佔空間,以用作下一輪存放索引中間結果的存儲區。參考下圖:

上圖是排序法創建索引中間結果的示意圖。創建過程:
讀入文檔後,對文檔進行編號,賦予惟一的文檔ID,並對文檔內容解析;
將單詞映射爲單詞ID;
創建(單詞ID、文檔ID、單詞頻率)三元組;
將三元組追加進中間結果存儲區末尾;
而後依次序處理下一個文檔;
當分配的內存定額被佔滿時,則對中間結果進行排序(根據單詞ID->文檔ID的排序原則);
將排好序的三元組寫入磁盤文件中。

注:在排序法創建索引的過程當中,詞典是一直存儲在內存中的,因爲分配內存是固定大小,漸漸地詞典佔用內存愈來愈大,那麼,越日後,可用來存儲三元組的空間愈來愈少。

創建好索引後,須要合併。
合併時,系統爲每一箇中間結果文件在內存中開闢一個數據緩衝區,用來存放文件的部分數據。將不一樣緩衝區中包含的同一個單詞ID的三元組進行合併,若是某個單詞ID的全部三元組所有合併完成,說明這個單詞的倒排列表已經構建完成,則將其寫入最終索引中,同事將各個緩衝區中對應這個單詞ID的三元組內容清空。緩衝區繼續從中間結果文件讀取後續的三元組進行下一輪合併。當全部中間結果文件都依次被讀入緩衝區,併合並完成後,造成最終的索引文件。

歸併法(Merge-based Inversion)

歸併法與排序法相似,不一樣的是,每次將內存中數據寫入磁盤時,包括詞典在內的全部中間結果都被寫入磁盤,這樣內存全部內容均可以被清空,後續創建索引可使用所有的定額內存。歸併法的示意圖以下所示:

 

與排序法的差別:
一、排序法在內存中存放的是詞典信息和三元組數據,詞典和三元組數據並無直接的聯繫,詞典只是爲了將單詞映射爲單詞ID。歸併法則是在內存中創建一個完整的內存索引結構,是最終文章索引的一部分。
二、在將中間結果寫入磁盤臨時文件時,歸併法將這個內存的倒排索引寫入臨時文件,隨後完全清空所佔內存。而排序法只是將三元組數據排序後寫入磁盤臨時文件,詞典做爲一個映射表一直存儲在內存中。
三、合併時,排序法是對同一單詞的三元組依次進行合併;歸併法的臨時文件則是每一個單詞對應的部分倒排列表,因此在合併時針對每一個單詞的倒排列表進行合併,造成這個單詞的最終倒排列表。

動態索引

在真實環境中,搜索引擎須要處理的文檔集合內有些文檔可能被刪除或者內容被修改。若是要在內容被刪除或修改以後立刻在搜索結果中體現出來,動態索引能夠實現這種實時性需求。動態索引有三個關鍵的索引結構:倒排索引、臨時索引和已刪除文檔列表。

臨時索引:在內存中實時創建的倒排索引,當有新文檔進入系統時,實時解析文檔並將其追加進這個臨時索引結構中。

已刪除列表:存儲已被刪除的文檔的相應文檔ID,造成一個文檔ID列表。當文檔被修改時,能夠認爲先刪除舊文檔,而後向系統增長一篇新文檔,經過這種間接方式實現對內容更改的支持。

當系統發現有新文檔進入時,當即將其加入臨時索引中。有新文檔被刪除時,將其加入刪除文檔隊列。文檔被更改時,則將原先文檔放入刪除隊列,解析更改後的文檔內容,並將其加入臨時索引。這樣就能夠知足實時性的要求。

在處理用戶的查詢請求時,搜索引擎同時從倒排索引和臨時索引中讀取用戶查詢單詞的倒排列表,找到包含用戶查詢的文檔集合,並對兩個結果進行合併,以後利用刪除文檔列表進行過濾,將搜索結果中那些已經被刪除的文檔從結果中過濾,造成最終的搜索結果,並返回給用戶。

索引更新策略

動態索引能夠知足實時搜索的需求,可是隨着加入文檔愈來愈多,臨時索引消耗的內存也會隨之增長。所以要考慮將臨時索引的內容更新到磁盤索引中,以釋放內存空間來容納後續的文檔,此時就須要考慮合理有效的索引更新策略。

徹底重建策略(Complete Re-Build)

對全部文檔從新創建索引。新索引創建完成後,老的索引被遺棄釋放,以後對用戶查詢的響應徹底由新的索引負責。在重建過程當中,內存中仍然須要維護老的索引對用戶的查詢作出響應。如圖所示

再合併策略(Re-Merge)

有新文檔進入搜索系統時,搜索系統在內存維護臨時倒排索引來記錄其信息,當新增文檔達到必定數量,或者指定大小的內存被消耗完,則把臨時索引和老文檔的倒排索引進行合併,以生成新的索引。過程以下圖所示:

更新步驟:

一、當新增文檔進入系統,解析文檔,以後更新內存中維護的臨時索引,文檔中出現的每一個單詞,在其倒排列表末尾追加倒排列表項,這個臨時索引可稱爲增量索引

二、一旦增量索引將指定的內存消耗光,增量索引和老的倒排索引內容須要進行合併。

高效的緣由:在對老的倒排索引進行遍歷時,由於已經按照索引單詞的詞典序由低到高排好順序,因此能夠順序讀取文件內容,減小磁盤尋道時間。

缺點:由於要生成新的倒排索引文件,因此老索引中的倒排列表沒發生變化也須要讀出來並寫入新索引中。增長了I/O的消耗。

原地更新策略(In-Place)

原地更新策略的出發點是爲了解決再合併策略的缺點。

在索引合併時,並不生成新的索引文件,而是直接在原先老的索引文件裏進行追加操做,將增量索引裏單詞的倒排列表項追加到老索引相應位置的末尾,這樣就可達到上述目標,即只更新增量索引裏出現的單詞相關信息,其餘單詞相關信息不變更。

爲了可以支持追加操做,原地更新策略在初始創建的索引中,會在每一個單詞的倒排列表末尾預留出必定的磁盤空間,這樣,在進行索引合併時,能夠將增量索引追加到預留空間中。以下圖:

實驗數據證實,原地更新策略的索引更新效率比再合併策略低,緣由:
一、因爲須要作快速遷移,此策略須要對磁盤可用空間進行維護和管理,成本很是高。
二、作數據遷移時,某些單詞及其對應倒排列表會從老索引中移出,破壞了單詞連續性,所以須要維護一個單詞到其倒排文件相應位置的映射表。下降了磁盤讀取速度及消耗大量內存(存儲映射信息)。

混合策略(Hybrid)

將單詞根據其不一樣性質進行分類,不一樣類別的單詞,對其索引採起不一樣的索引更新策略。常見作法:根據單詞的倒排列表長度進行區分,由於有些單詞常常在不一樣文檔中出現,因此其對應的倒排列表較長,而有些單詞不多見,則其倒排列表就較短。根據這一性質將單詞劃分爲長倒排列表單詞和短倒排列表單詞。長倒排列表單詞采起原地更新策略,而短倒排列表單詞則採起再合併策略。

由於長倒排列表單詞的讀/寫開銷明顯比短倒排列表單詞大不少,因此採用原地更新策略能節省磁盤讀/寫次數。而大量短倒排列表單詞讀/寫開銷相對而言不算太大,因此利用再合併策略來處理,則其順序讀/寫優點也能被充分利用。

查詢處理

創建好索引以後,如何用倒排索引來響應用戶的查詢呢?主要有下面三種查詢處理機制。

一次一文檔(Doc at a Time)

以倒排列表中包含的文檔爲單位,每次將其中某個文檔與查詢的最終類似性得分計算完畢,而後開始計算另一個文檔的最終得分,直到全部文檔的得分計算完畢爲止。而後根據文檔得分進行大小排序,輸出得分最高的K個文檔做爲搜索結果輸出,即完成了一次用戶查詢的響應。實際實現中,只需在內存中維護一個大小爲K的優先級隊列。以下圖所示是一次一文檔的計算機制示意圖:

虛線箭頭標出查詢處理計算的前進方向。查詢時,對於文檔1而言,由於兩個單詞的倒排列表中都包含這個文檔,因此能夠根據各自的TF和IDF等參數計算文檔和查詢單詞的類似性,以後將兩個分數相加獲得文檔1和用戶查詢的類似性得分Score1。其餘的也是相似計算。最後根據文檔得分進行大小排序,輸出得分最高的K隔文檔做爲搜索結果輸出。

一次一單詞(Term at a Time)

與一次一文檔不一樣,一次一單詞采起「先橫向再縱向」的方式,首先將某個單詞對應的倒排列表中的每一個文檔ID都計算一個部分類似性得分,也就是說,在單詞-文檔矩陣中首先進行橫向移動,在計算完某個單詞倒排列表中包含的全部文檔後,接着計算下一個單詞倒排列表中包含的文檔ID,即進行縱向計算,若是發現某個文檔ID已經有了得分,則在原先得分基礎上累加。當全部單詞都處理完畢後,每一個文檔最終的類似性得分計算結束,以後按照大小排序,輸出得分最高的K個文檔做爲搜索結果。 下圖是一次一單詞的運算機制。

虛線箭頭指示出了計算的前進方向,爲了保存數據,在內存中使用哈希表來保存中間結果及最終計算結果。在查詢時,對於文檔1,根據TD和IDF等參數計算這個文檔對」搜索引擎「的類似性得分,以後根據文檔ID在哈希表中查找,並把類似性得分保存在哈希表中。依次對其餘文檔計算後,開始下一個單詞(此處是」技術「)的類似性得分的計算。計算時,對於文檔1,計算了類似性得分後,查找哈希表,發現文檔1以及存在得分,則將哈希表對應的得分和剛剛計算獲得的得分相加做爲最終得分,並更新哈希表1中文檔1對應的得分,這樣就獲得文檔1和用戶查詢最終的類似性得分,相似的計算其餘文檔,最後將結果排序後輸出得分最高的K個文檔做爲搜索結果。

跳躍指針(Skip Pointers)

基本思想:將一個倒排列表數據化整爲零,切分爲若干個固定大小的數據塊,一個數據塊做爲一組,對於每一個數據塊,增長元信息來記錄關於這個塊的一些信息,這樣即便是面對壓縮後的倒排列表,在進行倒排列表合併的時候也能有兩個好處:

一、無須解壓全部倒排列表項,只解壓部分數據便可

二、無須比較任意兩個文檔ID。

下圖是將「Google」這個查詢詞對應的倒排列表加入跳躍指針後的數據結構。

假設對於「Google」這個單詞的倒排列表來講,數據塊的大小爲3。而後在每塊數據前加入管理信息,好比第一塊的管理信息是<<5,Pos1>>,5表示塊中第一個文檔ID編號,Pos1是跳躍指針,指向第2塊的起始位置。假設要在單詞「Google"壓縮後的倒排列表裏查找文檔ID爲7的文檔。首先,對倒排列表前兩個數值進行數據解壓縮,讀取第一組的跳躍指針數據,發現其值爲<5,Pos1>,其中Pos1指出了第2組的跳躍指針在倒排列表中的起始位置,因而能夠解壓縮Pos1位置處連續兩個數值,獲得<13,Pos2>。5和13是兩組數據中最小的文檔ID(即每組數據的第一個文檔ID),咱們要找的是7,那麼若是7號文檔包含在單詞」Google「的倒排列表中的話,就必定會出如今第一組,不然說明倒排列表中不包含這個文檔。解壓第1組數據後,根據最小文檔編號逆向恢復其原始的文檔編號,此處<2,1>的原始文檔ID是:5+2=7,與咱們要找的文檔ID相同,說明7號文檔在單詞」Google「的倒排列表中,因而能夠結束此次查找。

從上面的查找過程可知,在查找數據時,只須要對其中一個數據塊進行解壓縮和文檔編號查找便可得到結果,而沒必要解壓全部數據,很明顯加快查找速度,並節省內存空間。

缺點:增長指針比較操做的次數。

實踐代表:假設倒排列表的長度爲L(即包含L個文檔ID),使用根號L做爲塊大小,則效果較好。

多字段索引

即對文檔的多個字段進行索引。
實現多字段索引的方式:多索引方式、倒排列表方式和擴展列表方式。

多索引方式

針對每一個不一樣的字段,分別創建一個索引,當用戶指定某個字段做爲搜索範圍時,能夠從相應的索引裏提取結果。當用戶沒有指定特定字段時,搜索引擎會對全部字段都進行查找併合並多個字段的相關性得分,這樣效率較低。多索引方式示意圖以下:

倒排列表方式

將字段信息存儲在某個關鍵詞對應的倒排列表內,在倒排列表中每一個文檔索引項信息的末尾追加字段信息,這樣在讀出用戶查詢關鍵詞的倒排列表的同時,就能夠根據字段信息,判斷關鍵詞是否在某個字段出現,以此來進行過濾。倒排列表方式示意圖以下:

擴展列表方式

這是用得比較多的支持多字段索引的方法。爲每一個字段創建一個列表,該列表記錄了每一個文檔這個字段對應的出現位置信息。下圖是擴展列表的示意圖:

爲方便起見,只針對」標題「字段所創建擴展列表。好比第一項<1,(1,4)>,表明對於文檔1而言,其標題的位置爲從第一個單詞到第4個單詞這個範圍,其餘項含義相似。

對於查詢而言,假設用戶在標題字段搜索」搜索引擎「,經過倒排列表能夠知道文檔一、三、4包含這個查詢詞,接下來須要判斷這些文檔是否在標題字段中出現過查詢詞?對於文檔1,」搜索引擎「這個查詢詞的出現位置是6和10。而經過對應的標題擴展列表可知,文檔1的標題範圍是1到4,說明文檔1的標題內不包含查詢詞,即文檔1不知足要求。對於文檔3,」搜索引擎出現的位置是二、八、15,對應的標題擴展列表中,標題出現範圍爲1到3,說明在位置2出現的這個查詢詞是在標題範圍內的,即知足要求,能夠做爲搜索結果輸出。文檔4也是相似的處理。

短語查詢

短語查詢的本質是如何在索引中維護單詞之間的順序關係或者位置信息。較常見的支持短語查詢技術包括:位置信息索引、雙詞索引和短語索引。也可將三者結合使用。

位置信息索引(Position Index)

在索引中記錄單詞位置信息,能夠很方便地支持短語查詢。可是其付出的存儲和計算代價很高。示意圖以下:

<5,2,[3,7]>的含義是,5文檔包含「愛情「這個單詞,且這個單詞在文檔中出現2次,其對應的位置爲3和7,其餘的含義與此相同。

查詢時,經過倒排列表可知,文檔5和文檔9同時包含兩個查詢詞,爲了判斷在這兩個文檔中,用戶查詢是否以短語的形式存在,還要判斷位置信息。」愛情「這個單詞在5號文檔的出現位置是3和7,而」買賣「在5號文檔的出現位置是4,能夠知道5號文檔的位置3和位置4分別對應單詞」愛情「和」買賣「,即二者是一個短語形式,而根據一樣的分析可知9號文檔不是短語,因此5號文檔會被做爲搜索結果返回。

雙詞索引(Nextword Index)

統計數據代表,二詞短語在短語中所佔比例最大,所以針對二詞短語提供快速查詢,能解決短語查詢的問題。可是這樣作的話倒排列表個數會發生爆炸性增加。雙詞索引的數據結構以下圖:

由圖可知,內存中包含兩個詞典,分別是」首詞「和」下詞「詞典,」首詞「詞典有指向」下詞「詞典某個位置的指針,」下詞「詞典存儲了緊跟在」首詞「詞典的經常使用短語的第2個單詞,」下詞「詞典的指針指向包含這個短語的倒排列表。好比」個人「這個短語,其倒排列表包含文檔5和7,」的父親「這個短語,其倒排列表包含文檔5,其他詞典也是相似的含義。

對於查詢,用戶輸入」個人父親「進行查詢,搜索引擎將其進行分詞獲得」個人「和」的父親「兩個短語,而後分別查找詞典信息,發現包含」個人「這個短語的是文檔5和文檔7,而包含」的父親「這個短語的有文檔5。查看其對應的出現位置,能夠知道文檔5是符合條件的搜索結果,這樣就完成了對短語查詢的支持。

雙詞索引會使得索引急劇增大,通常實現並不是對全部單詞都創建雙詞索引,而是隻對計算代價高的短語創建雙詞索引。

短語索引(Phrase Index)

直接在詞典中加入屢次短語並維護短語的倒排列表。缺點就是不可能事先將全部短語都建好索引。通用作法就是挖掘出熱門短語。下圖是加入短語索引後的總體索引結構:

對於查詢,當搜索引擎接收到用戶查詢後,如今短語索引裏查找,若是找到,則計算後返回給用戶搜索結果,不然仍然利用常規索引進行查詢處理。

混合方法

將三者結合起來,接收到用戶查詢後,系統首先在短語索引中查找,若是找到則返回結果,不然在雙詞索引中查找,若是找到則返回結果,不然從常規索引中對短語進行處理,充分發揮各自的優點。3種方式的混合索引結構以下圖所示:

短語查詢用來對熱門短語和高頻短語進行索引,雙詞索引對包含停用詞等高代價短語進行索引。

對於查詢,系統首先在短語索引中查找,若是找到則返回結果,不然在雙詞索引中查找,若是找到則返回結果,不然從常規索引中對短語進行處理,這樣就充分發揮各自的優點。

分佈式索引(Parallel Indexing)

當搜索引擎須要處理的文檔集合太多的時候,就須要考慮分佈式解決方案。每臺機器維護整個索引的一部分,有多臺機器協做來完成索引的創建和對查詢的響應。

按文檔劃分(Document Paritioning)

將整個文檔集合切割成若干個子集合,而每臺機器負責對某個文檔子集合創建索引,並響應查詢請求。按文檔劃分示意圖以下:


工做原理:查詢分發服務器接收到用戶查詢請求後,將查詢廣播給全部索引服務器。每一個索引服務器負責部分文檔子集合的索引維護和查詢響應。當索引服務器接收到用戶查詢後,計算相關文檔,並將得分最高的K個文檔送返查詢分發服務器。查詢分發服務器綜合各個索引服務器的搜索結果後,合併搜索結果,將得分最高的m個文檔做爲最終搜索結果返回給用戶。

按單詞劃分(Term Paritioning)

每一個索引服務器負責詞典中部分單詞的倒排列表的創建和維護。按單詞劃分示意圖以下:

工做原理:一次一個單詞。假設查詢包含A、B、C三個單詞,查詢服務器接收到查詢後,將查詢轉發到包含單詞A倒排列表的索引服務器節點1,索引服務器節點1提取A的倒排列表,並累計計算搜索結果的中間的分,而後將查詢和中間結果傳遞給包含單詞B倒排列表的索引服務器節點,索引服務器節點2也是相似處理,並繼續到索引服務器節點3。而後將最終結果返回給查詢分發服務器,查詢分發服務器計算得分最高的K個文檔做爲搜索結果輸出。

兩種方案比較

按文檔比較經常使用,按單詞劃分只在特殊應用場合才使用。
按單詞劃分的不足:
可擴展性
搜索引擎處理的文檔是常常變更的。若是按文檔來對索引劃分,只須要增長索引服務器,操做起來很方便。但若是是按單詞進行索引劃分,則對幾乎全部的索引服務器都有直接影響,由於新增文檔可能包含全部詞典單詞,即須要對每一個單詞的倒排列表進行更新,實現起來相對複雜。

負載均衡
經常使用單詞的倒排列表很是龐大,可能會達到幾十M大小。若是按文檔劃分,這種單詞的倒排列表會比較均勻地分佈在不一樣的索引服務器上,而按單詞進行索引劃分,某個常見單詞的倒排列表所有內容都由一臺索引服務器維護。若是該單詞同時是一個流行詞彙,那麼該服務器會成爲負載過大的性能瓶頸。

容錯性
假設某臺服務器出現故障。若是按文檔進行劃分,那麼隻影響部分文檔子集合,其餘索引服務器仍然能響應。但若是按單詞進行劃分,若索引服務器發生故障,則某些單詞的倒排列表沒法訪問,用戶查詢這些單詞的時候,會發現沒有搜索結果,直接影響用戶體驗。

對查詢處理方式的支持
按單詞進行索引一次只能查詢一個單詞,而按文檔劃分的不受此限制。

總結

經過了解搜索引擎使用的數據結構和算法,對其工做原理有了進一步的認識。對於sphinx來講,在線上環境能夠考慮增量索引和一次全量索引結合達到實時性的效果。

因爲底層基礎比較差,花了大半個月重複讀了幾遍才能弄懂第三章講的內容,真正體會到數據結構和算法真的很重要。雖然平常工做不多會直接用到數據結構和算法,可是知道了經常使用的數據結構和算法以後,在遇到問題時就會有更多解決方案的思路,厚積薄發。

到此本文結束,若是還有什麼疑問或者建議,能夠多多交流,原創文章,文筆有限,才疏學淺,文中如有不正之處,萬望告知。

若是本文對你有幫助,望點下推薦,謝謝^_^

相關文章
相關標籤/搜索