日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

为Lucene选择快速唯一标识符(UUID)

發布時間:2023/12/3 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 为Lucene选择快速唯一标识符(UUID) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

大多數使用Apache Lucene的搜索應用程序都會為每個索引文檔分配唯一的ID(即主鍵)。 盡管Lucene本身不需要這樣做(它可能不太在乎!),但應用程序通常需要它以后通過其外部ID替換,刪除或檢索該文檔。 大多數在Lucene之上構建的服務器,例如Elasticsearch和Solr ,都需要一個唯一的ID,如果不提供,則可以自動生成一個ID。

有時,您的ID值已經預先定義,例如,如果外部數據庫或內容管理系統分配了ID ,或者您必須使用URI ,但是如果您可以自由分配自己的ID,那么哪種方法最適合Lucene?

一個明顯的選擇是Java的UUID類,該類生成版本4的通用唯一標識符 ,但事實證明,這是性能上最糟糕的選擇:它比最快的速度慢4倍。 要了解原因,需要對Lucene如何找到術語有所了解。

BlockTree術語詞典

術語詞典的目的是存儲在索引期間看到的所有唯一術語,并將每個術語映射到其元數據( docFreq , totalTermFreq等 )以及totalTermFreq (文檔,偏移量,投遞和有效載荷)。 當請求一個術語時,術語詞典必須在磁盤索引中找到它并返回其元數據。

默認編解碼器使用BlockTree術語詞典 ,該詞典以排序的二進制順序存儲每個字段的所有術語,并將這些術語分配到共享公共前綴的塊中。 默認情況下,每個塊包含25到48個詞。 它使用內存中的前綴三叉戟索引結構( FST )將每個前綴快速映射到相應的磁盤塊,并在查找時首先根據請求的術語的前綴檢查索引,然后在-disk塊并掃描以查找術語。

在某些情況下,當段中的術語具有可預測的模式時,術語索引可以知道請求的術語不能存在于磁盤上。 這種快速匹配測試可以帶來可觀的性能提升,尤其是當索引很冷(操作系統的IO緩存不緩存頁面)時,因為它避免了昂貴的磁盤搜尋。 由于Lucene是基于段的,因此單個id查找必須訪問每個段直到找到匹配項,因此快速排除一個或多個段可能是一個大勝利。 保持細分受眾群的數量盡可能少也很重要!

鑒于此,完全隨機的id(例如UUID V4 )應該會表現最差,因為它們擊敗了術語索引快速匹配測試,并且需要對每個段進行磁盤搜索。 具有可預測的每段模式的ID(例如順序分配的值或時間戳)應發揮最佳作用,因為它們將使術語索引快速匹配測試的收益最大化。

測試性能

我創建了一個簡單的性能測試器來驗證這一點。 完整的源代碼在這里 。 該測試首先將1億個ID索引到具有7/7/8段結構(7個大段,7個中段,8個小段)的索引中,然后搜索200萬個ID的隨機子集,記錄最佳時間5次。 我在Ubuntu 14.04上使用Java 1.7.0_55,以及3.5 GHz Ivy Bridge Core i7 3770K。

由于Lucene的術語從4.0開始是完全二進制的 ,因此存儲任何值的最緊湊的方法是二進制形式,其中每個字節使用所有256個值。 然后,一個128位ID值需要16個字節。

我測試了以下標識符來源:

  • 順序ID(0、1、2,...),采用二進制編碼。
  • 零填充的順序ID(00000000、00000001等),采用二進制編碼。
  • 納米時間,二進制編碼。 但是請記住, 納米時間是棘手的 。
  • 使用此實現從時間戳,nodeID和序列計數器派生的UUID V1 。
  • UUID V4 ,使用Java的UUID.randomUUID()隨機生成。
  • 片狀ID ,使用此實現 。

對于UUID和Flake ID,除了標準(16或36基)編碼之外,我還測試了二進制編碼。 請注意,我僅使用一個線程測試了查找速度,但是在添加線程時,結果應該線性擴展(在足夠并行的硬件上)。

用二進制編碼的零填充順序ID最快,比非零填充順序ID快很多。 UUID V4(使用Java的UUID.randomUUID() )慢了約4倍。

但是對于大多數應用程序來說,順序編號是不實際的。 第二快的是UUID V1 ,以二進制編碼。 令我驚訝的是,這比Flake ID快得多,因為Flake ID使用相同的原始信息源(時間,節點ID,序列),但是以不同的方式對位進行混洗以保留總體順序。 我懷疑問題在于,在獲取不同文檔之間的數字之前,必須在片狀ID中遍歷的通用前導數字的數目,因為64位時間戳的高位在先,而UUID V1則在低位位首先是64位時間戳。 當一個字段中的所有術語共享一個公共前綴時,術語索引也許可以優化這種情況。

我還分別測試了10、16、36、64、256的基數,通常對于非隨機ID,較高的基數更快。 我對此感到驚訝,因為我希望與BlockTree塊大小(25到48)匹配的基數最好。

此測試有一些重要警告(歡迎補丁)! 一個真正的應用程序顯然比簡單地查找id還要做更多的工作,并且結果可能會有所不同,因為熱點必須編譯更多活動的代碼。 在我的測試中,該索引非常熱(有大量RAM可以容納整個索引); 對于冷索引,我希望結果會更加鮮明,因為避免磁盤搜索變得非常重要。 在實際應用中,使用時間戳的id在時間上會更加分散; 我可以通過偽造更大范圍的時間戳來“模擬”自己。 也許這會縮小UUID V1和Flake ID之間的差距? 我在索引編制過程中只使用了一個線程,但是具有多個索引編制線程的實際應用程序會將ID一次分散到多個段中。

我使用了Lucene的默認TieredMergePolicy ,但是有一種更聰明的合并策略可能會支持那些ID更加“相似”的合并段,從而可能會產生更好的結果。 該測試不執行任何刪除/更新操作,這將在查找期間需要進行更多工作,因為如果給定的ID已被更新(除其中一個以外的所有其他ID),則該ID可能位于多個段中。

最后,我使用了Lucene的默認編解碼器,但是當您愿意將RAM換成更快的查詢時,我們有不錯的發布格式針對主鍵查找進行了優化,例如去年的Google夏季代碼項目和MemoryPostingsFormat 。 這些可能會提供可觀的性能提升!

翻譯自: https://www.javacodegeeks.com/2014/05/choosing-a-fast-unique-identifier-uuid-for-lucene.html

總結

以上是生活随笔為你收集整理的为Lucene选择快速唯一标识符(UUID)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。