Elasticsearch 2 (10) - 在Elasticsearch之下(深入理解Shard和Lucene Index)

來源:互聯網
上載者:User

標籤:應用   複雜   定址   預設   mit   sql   com   不能   介紹   

摘要

從底層介紹Elasticsearch Shard的內部原理,以及回答為什麼使用Elasticsearch有必要瞭解Lucene的內部工作方式?

  • 瞭解Elasticsearch API的代價

    • 構建快速的搜尋應用
    • 不要任何時候都commit
    • 何時使用Stored Fields和Document Values
    • Lucene可能不是一個合適的工具
  • 瞭解索引的儲存方式

    • term vector是索引大小的1/2
    • 我移除了20%的檔案,但是索引佔用空間並未發生任何變化
版本

elasticsearch版本: elasticsearch-2.2.0

內容索引

毫不誇張的說,如果不瞭解Lucene索引的工作方式,可以說完全不瞭解Lucene,對於Elasticsearch更是如此。

  • 可以使搜尋更快速
    • 可以冗餘資訊
    • 根據查詢(queries)建立索引
  • 在更新速度與查詢速度間妥協

    需要注意的是搜尋的應用情境

    • Grep vs. 全文檢索索引(full-text indexing)
    • Prefix queries vs. edge n-grams
    • Phrase queries vs shingles

    如果是進行首碼查詢(右模糊比對)或者是短語查詢(phrase queries),Elasticsearch可能不合適,需要做特殊的最佳化。(在2.x中,ES對以上應用情境都有支援,具體使用方式可以參考:Search in Depth)

  • Lucene索引的速度
    • http://people.apache.org/~mikemccand/lucenebench/indexing.html
建立索引

以兩個簡單的檔案為例:Lucene in action和Databases。

假設Lucene in action裡有單詞

{index, term, data, Lucene}

Databases裡有單詞

{sql, index, data}
  • 樹形結構(Tree structure)

    對於range query有序
    查詢的時間複雜度為O(log(n))

    一般的關係型資料庫大致結構可能是上面這樣的一顆B、B+樹,但是Lucene是另外一種儲存結構。

  • 倒排索引(或反向索引Inverted Index)

    對於Lucene來說,其主要的儲存結構是一個反向索引,它是一個數組,數組裡面是一個有序的資料字典。

    這樣一個儲存結構存在與Lucene的Segment裡。

    • term ordinal —— 是一個詞的序號
    • term dict —— 是詞的內容
    • postings list —— 存放包含詞的檔案的id序列
    • doc id —— 是每個檔案的唯一標識
    • document —— 存放每個檔案的內容

    這兩種結構的一個重要區別是:在增加或刪除檔案時,系統會樹形結構頻繁操作,這個結構是一直變化的,而反向索引可以維持不變(Immutable)。

  • 插入?
    • 插入 即 建立一個新的segment
    • 當有很多segment時,系統會合并segment
      這個過程本質上是一個merge sort,做的事情就是

      • 串連檔案
      • 合并字典
      • 合并postings lists

  • 刪除?
    • 刪除要做的只是置一個標誌位
    • 搜尋及merge的時候系統會忽略被刪除的檔案
    • 當有很多刪除發生時,系統會自動運行merge
    • 被標記為已刪除的檔案會在merge完成後回收其所佔用的儲存空間

  • 孰優孰劣?
    • 當更新一個檔案的時候,我們實際上是建立了一個新的segment,因此

      • 單個檔案的更新代價高昂,我們需要使用bulk更新
      • 所有的寫操作都是順序執行的
    • Segments永遠不會被修改

      • 檔案系統快取友好
      • 不會出現鎖的問題
    • Terms 高度去重

      • 節省大量高頻詞所佔用的空間
    • 檔案本身由唯一序號標識

      • 跨API通訊的時候非常方便
      • Lucene可以在單個Query下使用多個索引index
    • Terms 由唯一序號標識

      • 對於排序非常重要,只需要比較數字,而非字串
      • 對於faceting(分面搜尋)非常重要
  • Lucene Index的強大之處(Index intersection)

    很多資料庫不支援同時使用多個索引,但是Lucene支援

    • Lucene為postings lists 維護一個skip list(Wiki),如果要搜尋如上例子中的“red shoe”,系統參考skip list裡的資訊可以跳躍檢索(“leap-frog”)

    • 對於很多資料庫,它們會挑選最主要的索引(most selective),而忽略其他

    關於詳細的index intersection演算法以及如何使用skip list的可以參照(nlp.standford.edu)

更多索引
  • 術語向量(Term vectors)
    • 為每個檔案都會建立一個反向索引(Inverted Index)
    • 適用情境:搜尋更相似的內容
    • 也可以用作高亮搜尋結果

  • 檔案值(Document Values)
    • 以檔案欄位為單位進行列式儲存
    • 適用情境:排序、權重記分

  • 有序(集合)檔案值
    • 檔案有序、欄位有序

      • 單欄位:排序
      • 多欄位:分面搜尋

  • 分面搜尋(Faceting)

    分面是指事物的多維度屬性。例如一本書包含主題、作者、年代等分面。而分面搜尋是指通過事物的這些屬性不斷篩選、過濾搜尋結果的方法。可以將分面搜尋看成搜尋和瀏覽的結合。分面搜尋作為一種有效搜尋方式,已經被用在電子商務、音樂、旅遊等多個方面。

    例如,Google音樂的挑歌頁面,將歌曲分為節奏、聲調、音色、年代、流派等分面

    • 根據檔案與搜尋匹配的情況計數

      • 例如,電商網站根據衣服的款式、衣長、尺碼、顏色等分面。
    • 簡單(naive)方案

      • 利用雜湊表計數(value to count)
      • O(#docs) ordinal 尋找
      • O(#doc) value 尋找
    • Lucene方案

      • 雜湊表(ord to count)
      • 最後統計值
      • O(#docs) ordinal 尋找
      • O(#values) value 尋找

    因為ordinal是密集的,所以可以簡單用數組array來表示。

  • 如何使用API?

    Elasticsearch進階API 都是基於Lucene API構建的,這些基礎的API包括:

    -----------------------------------------------------------------------------------------------    API                 |   用途                                  |   方法-----------------------------------------------------------------------------------------------     Inverted index      | Term -> doc ids, positions, offsets   |   AtomicReader.fields-----------------------------------------------------------------------------------------------     Stored fields       | Summaries of search results           |   IndexReader.document-----------------------------------------------------------------------------------------------     Live docs           | Ignoring deleted docs                 |   AtomicReader.liveDocs-----------------------------------------------------------------------------------------------         Term vectors        | More like this                        |   IndexReader.termVectors-----------------------------------------------------------------------------------------------    Doc values/Norms    | Sorting/faceting/scoring              |   AtomicReader.get*Values-----------------------------------------------------------------------------------------------     
  • 小結
    • 資料有四份重複,只是結構各不相同

      • 絕不是浪費空間
      • 感謝immutable使資料易於管理
    • Stored Fields和Document Values

      • 兩種結構為不同的使用情境最佳化

        1. 少量檔案擷取多個欄位:Stored Fields
        2. 大量檔案擷取少量欄位:Document Values

檔案格式的秘密
  • 不能忘的規則
    • 儲存檔案的控制代碼

      不要為每個欄位每個檔案使用檔案

    • 避免磁碟定址

      磁碟定址的時間大概為~10ms

    • 不要忽略檔案系統的緩衝

      隨機訪問小檔案還是可以的

    • 使用輕壓縮

      • 更少I/O
      • 更小索引
      • 檔案系統快取友好
  • 編碼解碼
    • 檔案格式依賴與編碼解碼
    • 預設的編碼格式已經最佳化記憶體與速度之間的關係

      不要使用RAMDirectory、MemoryPostingsFormat、MemoryDocValuesFormat。

    • 詳細資料參照

      http://lucene.apache.org/core/4_5_1/core/org/apache/lucene/codecs/packagesummary.
      html

  • 合適的壓縮技術
    • Bit packing / vlnt encoding

      • postings lists
      • numeric doc values
    • LZ4

      • code.google.com/p/lz4
      • 輕量壓縮演算法
      • Stored fields, term vectors
    • FSTs

      • Map<string, ?="">
      • 鍵共用首碼(prefix)和尾碼(suffix)
      • terms index
  • TermQuery的背後
    1. Terms Index

      在索引中尋找相應的詞

      • 在記憶體中FST儲存了詞的首碼prefix
      • 提供詞在字典中的位移量
      • 在不存在時可以快速失敗

    2. Terms Dictionary

      • 跳到字典位移的位置

        壓縮是基於共用首碼的,與“BlockTree term dict”類似

      • 順序讀取直到找到特定的Term

    3. Postings List

      • 跳到postings list位移量對應位置
      • 用改進的FOR(Frame of Reference)進行增量編碼

        1. 增量編碼
        2. 將塊拆分為N=128個值的大小
        3. 每個塊使用位壓縮(bit packing)
        4. 如果有剩餘文檔,使用vlnt壓縮

    4. Stored Fields

      • 對一個子集的doc id,索引存於記憶體中

        高效記憶體(monotonic)壓縮

        二分尋找

      • 欄位

        順序儲存

        使用16KBBlock Storage壓縮

  • 查詢過程小結
    • 每個欄位2次磁碟定址
    • 每個檔案1次磁碟定址(Stored Fields)

    • terms dict/postings lists都在檔案系統的緩衝中

      此時不會發生磁碟定址

    • “脈衝”最佳化

      • 對於唯一的term,postings list儲存在Terms dict中
      • 1次磁碟定址
      • 永遠作為主鍵
效能

中系統效能出現兩次下降,可能的情況是

  1. 索引增長超過檔案系統快取的大小

    Stored Fields不再全部儲存於緩衝中

  2. Terms dict/Postings lists不全在緩衝中

參考

參考來源:

SlideShare: What is in a Lucene index?

Youtube: What is in a Lucene index? Adrien Grand, Software Engineer, Elasticsearch

SlideShare: Elasticsearch From the Bottom Up

Youtube: Elasticsearch from the bottom up

Wiki: Document-term matrix

Wiki: Search engine indexing

Skip list

Standford Edu: Faster postings list intersection via skip pointers

分面搜尋(Faceted Search)

StackOverflow: how an search index works when querying many words?

StackOverflow: how does lucene calculate intersection of documents so fast?

Lucene and its magical indexes

結束

Elasticsearch 2 (10) - 在Elasticsearch之下(深入理解Shard和Lucene Index)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.