Lucene in Action-構建索引

文檔和域(document、filed)算法

  • 索引過程,將原始數據轉換成Lucene能識別的 document和filed
  • 搜索過程,被搜索對象爲域值

Lucene 索引過程數組

  • 分析過程,將域文本處理成大量語彙單元

  1. 提取文本、建立文檔
  2. 分析文檔
    • 分析文本,先將其轉換成語彙單元串
      • 也包括一系列可選操做:好比去除無心義詞語,改變詞語的狀態等
    • IndexWriter 的 addDocument
  3. 向索引添加文檔
    • 倒排索引存儲結構,有效利用磁盤空間
    • 將語彙單元做爲查詢關鍵字,而不是整個文檔
    • 索引段
      • Lucene 索引都包含一個或多個段
        • 每一個段都是獨立索引
        • 是整個文檔索引的子集
        • 每當write刷新緩存區增長的文檔、掛起目錄、刪除操做,都會新增長一個段
        • 搜索索引時,每一個段獨立訪問,結果合併返回
      • 每一個段包含多個文件
        • 格式爲 _x.<ext>
        • .<ext>爲擴展名,表示對應的索引的某個部分
        • 壓縮成單一文件:_X.cfs
      • 特殊文件:段文件  _<N>
        • 指向全部激活的段
        • Lucene 先打開它,再去打開他指向的段
        • <N> 表明整數,修改一次索引 加1
      • 段集聚太多
        • 週期性合併一些段成新的段(而後刪掉老的多個段)

基本索引操做緩存

  • 向索引中添加文檔
  • 刪除索引文檔
      • 優化刪除,強制合併索引段
  • 更新索引文檔
    • Lucene沒法作到更新操做
    • 只能刪除整個文檔,再向索引中添加新文檔

域選項安全

  • Filed 類是索引其間很重要的類
    • 控制着被索引的域值
  • 域選項 包括:域索引選項、域存儲選項、域項向量選項
  • 域索引選項
  • 域存儲選項
  • 域項向量選項
    • 是否進行向向量計算
      • 計算匹配度
  • 域選項組合
  • 域排序選項
  • 多值域
    • 一個域包括多個值(好比多個做者)

對文檔和域進行加權併發

  • 加權能夠在索引其間完成
  • 也能夠在搜索其間完成
    • 搜索階段加權更加動態,更消耗CPU
    • 好比:能夠詢問用戶是否對最近修改過的文檔進行加權
  • 加權要當心
    • 特別是未通知用戶的加權,會使得結果變得很詭異
  • 文檔加權
    • 默認全部文檔的加權因子都是 1.0
    • setBoost(float )
  • 域加權操做
    • 加權文檔會,對全部的域進行加權
    • 也能夠單獨對某個域加權
    • 較短的域有隱含加權,這是Lucene 評分算法有關(以前博客已經提到過)
  • 加權因子可能須要實驗得到而最佳值
    • 注意,改變 加權因子,須要刪除文檔在添加
      • 固然 update 方法也有一樣效果
    • 高級操做,使用時要當心
    • Lucene 評分機制包含大量因子,加權因子僅僅是其中一個
  • 加權基準(Norms)
    • 索引期間,文檔域的鎖有加權被合併成一個浮點數
    • setNorm 是高級方法,須要程序本身計算本身的 Norms
    • 常常面臨搜索其間高內存
    • 索引一半,關閉norms ,仍然須要重建索引
      • 段合併會致使norms擴散

索引數字優化

  • 一種是:數字包含在將要索引的文本中
    • 須要將其做爲單獨的語彙單元處理
    • 選擇不丟棄數字的分析器便可
  • 另外一種場景:一些域僅僅包含數字
    • 數字域值進行索引:支持精確匹配、範圍搜索、數字排序
    • NumericFiled
      • 每一個數字索引用特里結構索引
        • Trie(特里結構,字典樹)
      • 只接受單一數值
        • 多數值可能致使排序不肯定
      • 高級參數:precisionStep
        • 控制間隙,間隙越小,特里括號越多,會增大索引尺寸
  • 索引日期和時間
    • 轉換成數字

域截取搜索引擎

  • 索引時須要限制須要索引的文檔
    • 好比二進制文檔(好比很大的視頻),錯誤分類
    • 好比有時僅僅須要對部分文檔進行索引
    • setMaxFiledLength
  • 謹慎使用,可能會致使有的東西找不到

近實時搜索線程

  • Lucene重要功能(實時搜索)
  • 及時索引,及時搜索
    • 該方法實時刷新緩存區,新增或刪除文檔
    • indexWriter 立刻刷新緩存,不等內存滿了在刷新

優化索引3d

  • 就是將多個段合併成一個或少許段
  • 提升搜索速度,不是索引速度
  • IndexWriter 4個索引優化方法
  • 消耗大量CPU和I/O資源
    • 是一次性大量系統開銷換取搜索速度變快
    • 若是優化伴隨大量搜索請求,權衡使用優化
  • 因爲舊段在commit 前 不會被刪除
    • 因此 要預留大約三倍的磁盤空間
    • 優化後,佔用磁盤空前會比優化以前少

FSDirectory 的幾個子類::調試

  • 全部子類寫操做都共享代碼
  • FSDirectory.open 會自動匹配調取子類 
  • RAMDirectory 讀寫都在內存
  • 兩個directory 之間 靜態拷貝
    • 盲目覆蓋、沒有鎖機制

併發、安全和鎖

  • 線程安全和多虛擬機安全
  • 遠程文件系統訪問索引
    • 本機保存修改本地索引,其餘機器經過遠程文件系統搜索該索引
      • 效果不好
    • 最好的方法是把本地索引複製到各個計算機
      • Solr 商業化搜索引擎,很好的支持該策略

索引鎖機制

  • Lucene 採用基於文件的鎖
  • 容許你修改鎖實現方法:Directory.setLockFactory
    • 將任何 LockFactory 的子類設置爲本身的實現鎖 
  • 一般不用擔憂程序在使用哪一個鎖
    • 多臺機器、多虛擬機纔會用到本身實現的鎖
    • 以便輪流進行索引操做

調試索引:

  • 輸出調試信息到標準輸出

高級索引概念

  • IndexReader 刪除文檔
  • Lucene 只容許 一個寫操做
    • IndexReader 刪除文檔時,須要關閉 IndexWriter
      • 所以,程序交叉完成添加、刪除會極大的影響吞吐
      • 更好的辦法是將添加和刪除 批量交給IndexWriter
  • 回收被刪除文檔所用過的磁盤空間
    • bit 數組記錄被刪除索引文檔(速度很快)
    • 這些文檔數據依然佔用磁盤空間
      • 段合併時纔會回收
        • optimize 會觸發段合併,致使回收(合併全部段)
        • expungeDeletes 會使被掛起刪除操做相關文檔合併段(合併相關文檔,開銷相對小,但也很大)
  • 緩衝和刷新
    • 新文檔添加到Lucene 索引或 掛起一個刪除操做
      • 這些操做首先被緩存到內存中
        • 主要爲了下降磁盤 IO
      • 這些操做會以新段週期性的保存至Directory 中
    • IndexWriter 三種可能觸發刷新
      • 默認 RAM 緩存是16M
    • 發生刷新時:
      • writer 會在Directory 建立新段和被刪除文件
        • 這些文件對於新打開的IndexReader 不可見、不可用
        • 直到writer commit、close
        • 新打開的reader 才能看到
      • 刷新是釋放緩存的更改操做
      • 提交是讓更改在索引中可見
  • 索引提交
    • 調用 commit 方法之一會建立新的索引提交
      • commit ()
      • commit (Map<String,String>) 將提交的map  以元數據形式不透明提交
    • 新打開的IndexReader、IndexSearch 只會看到上次提交後的索引
      • 近實時搜索功能除外
        • 該功能下,不用向磁盤提交便可搜索
    • 提交操做開銷大,頻繁下降索引吞吐量
    • rollBack()
      • 刪除當前IndexWriter 上下文,在上一次提交前的全部更改操做
    • 提交的步驟:
      • 上次提交的舊索引文件,會到新提交完成後才刪除
        • 兩次提交間距太長時間,消耗磁盤空間比 頻繁提交更多
    • 兩階段提交:
      • Lucene 提供了 prepareCommit() 、prepareCommit(Map<String,String>)
        • 這倆方法會完成上述的步驟一、2
        • 大多數完成步驟3
        • 可是不能使新的segment_N 對reader 可見
      • prepareCommit 後,必須調用 rollback 或commit
        • 此時,commit 執行的很快
    • 索引刪除策略
      • IndexDeletionPolicy
        • 負責通知IndexWriter 什麼時候刪除舊的提交
        • 默認策略是每次提交先刪除舊的提交
          • KeepOnlyLastCommitDeletionPolicy
    • 管理多個索引提交
      • 回滾到好久之前版本
    • Lucene 實現了事務
      • 一次僅能打開一個事務
      • 硬件崩潰,索引不會毀壞,回滾到上次提交
        • 一些狀況下,請禁止底層 I/O 的寫緩存
  • 合併段
    • 帶來的好處:
    • 段合併策略
      • 兩種策略都是 LogMergePolicy 的子類
        • LogByteSizeMergePolicy
          • 根據該段包含全部文件的總字節數
        • LogDocMergePolicy
          • 根據段中文檔數量
          • 差異較大,最好使用第一種
        • 兩者都不會刪除文檔
        • 能夠繼承 MergePolicy 實現本身的段合併策略
          • 舉例能夠實現基於時間的合併策略(非搜索高峯期執行)
          • 是否進行合併,取決於
            • mergeFactor 的值爲0的段大小的平方 等於爲1段尺寸大小
            • 小於 minMergeMB ,降級爲更低級別的段
            •  大於或等於mergeFactor級別 設定的段尺寸,進行段合併
            • 級別越高,合併的頻率越低
            • 超過最大值(maxMergeMB、maxMergeDocs)
              • 永久不被合併
            • mergeFactor 值設置的越大,合併頻率也越低
      • 在進行 optmize、explungDeletes 時,
        • 會對要被合併的段進行選擇
        • 合併策略可自定義
          • 好比:跳過超出某個大段的合併
            • 對包含10% 被刪除文檔的段合併
      • 隨着時間推移,
        • 出現少許很大的段
        • 少許比 mergeFactor 更小的段
        • 段的數量與段尺寸的對數成正比
        • 這樣比較有利於段數量維持在較低的值
          • 較少段合併
          • 提升吞吐量
    • MergerScheduler
      • 選取後,開始實行合併
      • ConcurrentMergerScheduler
        • 執行後臺線程進行合併
      • SerialMergerScheduler
        • 調用者合併
      • 能夠本身實現合併方法,繼承MergerScheduler
        • 本身實現是很是高級的用法
相關文章
相關標籤/搜索