close

點擊上方「Java基基」,選擇「設為星標」

做積極的人,而不是積極廢人!

每天14:00更新文章,每天掉億點點頭髮...

源碼精品專欄

原創 | Java 2021超神之路,很肝~

中文詳細注釋的開源項目

RPC 框架 Dubbo 源碼解析

網絡應用框架 Netty 源碼解析

消息中間件 RocketMQ 源碼解析

數據庫中間件 Sharding-JDBC 和 MyCAT 源碼解析

作業調度中間件 Elastic-Job 源碼解析

分布式事務中間件 TCC-Transaction 源碼解析

Eureka 和 Hystrix 源碼解析

Java 並發源碼

來源:blog.csdn.net/shenmingxueIT/

article/details/121843522

索引
倒排索引
單詞詞典
動態索引
索引的建立
索引更新
多字段索引


索引

搜索引擎的索引其實是實現<關鍵詞,文檔>映射的具體的數據結構 ,其實現方式也是多種多樣的:倒排索引、簽名文件以及後綴樹等等 。實驗證明倒排索引 是最有效的實現方式,同時也是當前搜索引擎廣泛應用的索引技術。

基於 Spring Boot + MyBatis Plus + Vue & Element 實現的後台管理系統 + 用戶小程序,支持 RBAC 動態權限、多租戶、數據權限、工作流、三方登錄、支付、短信、商城等功能

項目地址:https://gitee.com/zhijiantianya/ruoyi-vue-pro
視頻教程:https://doc.iocoder.cn/video/
倒排索引

平常我們想要查詢一個關鍵詞,最簡單的思路肯定是挨個每個文檔查看這個文檔是否存在這個關鍵詞,這就是建立<文檔,關鍵詞>這樣映射的索引。詳情圖示如下,大概解釋一下,這裡的網頁A中假設就是這篇博客,後面跟的是這篇博客中的關鍵詞。

這樣我們想查找索引 這個關鍵詞的時候,我們就需要先查網頁A,然後對它的關鍵詞一個個遍歷,直到遍歷完所有的網頁。這樣的過程時間複雜度是O(n2),即便後面的關鍵詞列表我們用的是紅黑樹等高級數據結構,那樣最快的時間複雜度則是O(nlogn)。這樣的技術應用在搜索引擎這種特別依賴反應時間來滿足用戶需求的應用上就顯得非常吃力,這也是為什麼要採取倒排索引 的原因。倒排索引會建立<關鍵詞,文檔> 的映射,如下圖所示:

這樣我們想要搜索關鍵詞的時候,只需要經過一遍O(n)的過程就能得到我們想要的答案。如果用更好的數據結構且不在乎價格的話,甚至可以直接用哈希得到O(1)的效果。而實際上的數據結構可能並不是圖示這樣,其一般會採用這樣的數據結構:

//定義倒排索引structInvertedList{list<IndexElement>inverted_list_;};//定義倒排索引裡面的每個元素structIndexElement{intword_id_;//單詞idstringword_;//單詞名稱list<DocumentInfo>documents_;//包含單詞的文檔};structDocumentInfo{intdocument_id_;//文檔idintword_count_;//此文檔中出現這個單詞的次數vector<int>word_index_;//每次這個單詞出現的位置信息};

可以看到,我們這裡多加了word_count_以及word_index_這兩個變量,這是因為文檔中單詞的頻率信息是在計算網頁相關度中非常重要的一個指標。而詞彙出現的位置對於短語查詢來說非常有用,這兩個都會在後面的博客中進行介紹。

注 :實際上並不村存儲倒排索引項中實際文檔編號,而是代之以文檔編號的差值,這樣的目的其實是省空間,更好的進行數據的壓縮。

單詞詞典

單詞詞典是倒排索引中非常重要的組成部分,其用來維護文檔集合中出現的所有單詞的相關信息。實現方式多種多樣,常有的就是哈希+鍊表、B+樹、紅黑樹等等。

哈希+鍊表形式 :這種形式會形成如下圖一般的單詞詞典,其是單詞經過一個哈希函數得到一個下標。假設索引 這個單詞單詞經過如下函數運算得到下標位0,我們就把這個倒排索引放到這個哈希桶裡面,但是這個桶裡面已經有MySQL 這個單詞了,這就產生了哈希衝突,這也就是我們為什麼需要鍊表的原因了。另外,哈希+鍊表的時間複雜度是O(1)+O(m),如果想要進一步優化,那麼我們可以借鑑Java的思想,當鍊表長度超過閾值的時候就改用紅黑樹。
intget_index(stringword){returnhash(word);}
B+樹 :B+數是一種常用的查找結構,其在MySQL中可謂是大放異彩。其和哈希+鍊表不同的是,其需要單詞能夠按照大小排序。對於其,由於大家應該挺熟悉的,這裡就不對其多加解釋了。
動態索引

在搜索引擎的應用中,網頁往往不是靜態的,其會是動態變化的。搜索引擎為了滿足這種動態變化的需求就不得不使用三個工具:倒排索引、臨時索引和已刪除文檔列表。

當搜索引擎系統發現有新的文檔被爬蟲下載,會先將其加入臨時索引中;如果有文檔被刪除,則將其加入刪除文檔隊列;文檔被更改的話,將原來的文檔加入刪除文檔隊列,更改後的文檔加入臨時文檔隊列。

如果是用戶的查詢請求的話,就會從臨時隊列和倒排索引中都進行查詢,對兩個結果進行合併,之後再查詢刪除文檔隊列,進行一個文檔過濾。

索引的建立兩遍文檔遍曆法

這個方法需要對文檔集合進行兩遍掃描。第一遍掃描的時候,並沒有立即開始創建索引,而是先收集一些全局的統計信息:網頁集合中網頁個數WebPageNum、網頁集合內包含的單詞數量WordCount,每個單詞在多少文檔中出現過的次數DF。得到這些信息的目的是為了知道我們需要開闢多大的內存,需要什麼資源 。

第二遍遍歷就是真正建立倒排索引的時候,我們先會獲取包含這個單詞的每個文檔的文檔ID,以及這個單詞在文檔中出現的次數。不斷重複這個過程,知道填滿我們申請的內存空間。

兩遍文檔遍曆法是非常消耗IO資源的,所以我們往往採用在內存中去構建索引,這要求我們要有錢整個大的內存。

歸併法

歸併法是兩遍文檔遍曆法的改進,該方法在建立索引的過程中,始終在內存中分配固定大小的空間,用來存放詞典信息和所以對中間結果,當分配的空間被消耗光的時候,就把中間寫過寫入磁盤,和磁盤中間的結果進行合併。這樣內存就可以反覆復用,比較省錢。

索引更新

像在內存中維護的索引往往都會到達內存的上線,這個時候我們就要考慮把索引合併到磁盤上,以釋放內存空間容納新的電腦。常用的更新策略如下:

完全重建策略 :當新增文檔達到一定數量的時候,我們將新增文檔和原先的文檔進行合併,在這個過程對所有文檔重新建立索引 。這個過程由於時間較長,在索引重建的過程中,內存仍然維護合併前的索引對查詢做出響應。
再合併策略 :和完全重建所有文檔不同,再合併針對的是新增文檔,對其建立索引之後,把新索引和老索引進行合併 。
原地更新策略 :這個是對再合併策略的改進。策略假設就是老索引是沒有變化的,這樣對於新文檔,我們直接把它加入到老索引 之中,這樣就可以省去在內存建立新文檔索引的過程。

基於 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實現的後台管理系統 + 用戶小程序,支持 RBAC 動態權限、多租戶、數據權限、工作流、三方登錄、支付、短信、商城等功能

項目地址:https://gitee.com/zhijiantianya/yudao-cloud
視頻教程:https://doc.iocoder.cn/video/
多字段索引

在搜索引擎實際應用中,由於網頁中是有一定結構的:標題,引用,正文等等。如果說平常索引是判斷此文檔是否出現過關鍵詞,那麼多索引是判斷此關鍵詞是在文檔的哪一部分出現。而對於這種多字段類型的文檔,搜索引擎實現方式主要有以下幾種:

多索引方式 :其針對每個不同的字段,分別建立一個索引,當用戶指定某個字段作為搜索範圍的時候,可以從相應的索引中提取結果;當用戶沒有指定特定字段的時候,搜索引擎會對所有字段都進行查找併合並多個字段的相關性得分,根據得分給出搜索結構。
倒排列表 :假設文檔包含三個字段:標題、引用、正文。那麼我們可以用三個比特位進行標識,這樣就會形成如下圖的倒排索引結構,這裡每個倒排索引項格式如此<DocumentID,WordCount,Filed,Position>,那麼第一項就可以表示關鍵詞索引在198號文檔中出現了兩次,位置是引用和正文兩個位置。
擴展列表方式 :這個是實際中用的比較多的多字段索引方式,其為每個字段建立一個擴展列表。而倒排索引項會記錄<DocumentID,WordCount,Position>這麼一個三元關係,但是其還包含多個個擴展項中,其中記錄<DocumentID,FIledRange>這麼一個關係,具體如下:假設我們搜索關鍵詞索引,這個時候根據倒排列表項,我們知道在198號文檔中出現了兩次,一次在2號位置,一次在10號位置。根據標題擴展列表,我們知道標題返回是1號~6號位置,那麼2號位置在標題中。根據正文擴展列表,我們知道10號位置是正文部分,這樣就達到了多索引的目的。雖然這種方式可能有兩次查詢的過程,但是它可以服用單索引,這也是常用的原因。

歡迎加入我的知識星球,一起探討架構,交流源碼。加入方式,長按下方二維碼噢:

已在知識星球更新源碼解析如下:

最近更新《芋道 SpringBoot 2.X 入門》系列,已經 101 余篇,覆蓋了MyBatis、Redis、MongoDB、ES、分庫分表、讀寫分離、SpringMVC、Webflux、權限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能測試等等內容。

提供近 3W 行代碼的 SpringBoot 示例,以及超 6W 行代碼的電商微服務項目。

獲取方式:點「在看」,關注公眾號並回復666領取,更多內容陸續奉上。

文章有幫助的話,在看,轉發吧。

謝謝支持喲 (*^__^*)

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 鑽石舞台 的頭像
    鑽石舞台

    鑽石舞台

    鑽石舞台 發表在 痞客邦 留言(0) 人氣()