精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

億級ES數據搜索性能優化

OSC開源社區 ? 來源:OSC開源社區 ? 2023-05-26 14:55 ? 次閱讀

1

背景

2020年以來內容標注結果搜索就是社區中后臺業務的核心高頻使用場景之一,為了支撐復雜的后臺搜索,我們將社區內容的關鍵信息額外存了一份到Elasticsearch中作為二級索引使用。隨著標注業務的細分、迭代和時間的推移,這個索引的文檔數和搜索的RT開始逐步上升。 下面是這個索引當前的監控情況。 2e89cb94-fb6b-11ed-90ce-dac502259ad0.png

本文介紹社區利用IndexSorting,將億級文檔搜索性能由最開始2000ms優化到50ms的過程。如果大家遇到相似的問題和場景,相信看完之后一定能夠一行代碼成噸收益。

2

探索過程

2.1 初步優化

最開始需求很簡單,只需要最新發布的動態分頁展示。這時候實現也是簡單粗暴,滿足功能即可。查詢語句如下:

GET /content-alias/_search
{
  "track_total_hits": true,
  "sort": [
    {
      "publish_time": {
        "order": "desc"
      }
    }
  ],
  "size": 10
}

由于首頁加載時沒加任何篩選條件,于是變成了從億級內容庫中找出最新發布的10條內容

針對這個查詢很容易發現問題出現在大結果集的排序,要解決問題,自然的想到了兩條路徑:

去掉sort

縮小結果集

經過用戶訴求和開發成本的權衡后,當時決定“先扛住,再優化”:在用戶打開首頁的時候,默認增加“發布時間在最近一周內”的篩選條件,這時語句變成了:

GET /content-alias/_search
{
  "track_total_hits": true,
  "query": {
    "bool": {
      "filter": [
        {
          "range": {
            "publish_time": {
              "gte": 1678550400,
              "lt": 1679155200
            }
          }
        }
      ]
    }
  },
  "sort": [
    {
      "publish_time": {
        "order": "desc"
      }
    }
  ],
  "size": 10
}

這個改動上線后,效果可以說是立竿見影,首頁加載速度立馬降到了200ms以內,平均RT60ms。這次改動也為我們減小了來自業務的壓力,為后續的優化爭取了不少調研的時間。

雖然搜索首頁的加載速度明顯快了,但是并沒有實際解決根本問題——ES大結果集指定字段排序還是很慢。對業務來說,結果頁上的一些邊界功能的體驗依舊不能盡如人意,比如導出、全量動態的搜索等等。這一點從監控上也能夠較明顯的看出:慢查詢還是存在,并且還伴隨著少量的接口超時。

2e95414a-fb6b-11ed-90ce-dac502259ad0.png

老實說這個時期我們對于ES的了解還比較基礎,只能說會用、知道分片、倒排索引、相關性打分,然后就沒有了。總之我們有了方向,開始奮起直追。

2.2 細致打磨

2.2.1 知識積累

帶著之前遺留的問題,我們開始開始重新出發,從頭學習ES。要優化搜索性能,首先我們要知道的是搜索是怎么做的。下面我們就以一個最簡單的搜索為例,拆解一下整個搜索請求的過程。

(1)搜索請求

GET /content-alias/_search
{
  "track_total_hits":false,
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "category_id.keyword": "xxxxxxxx"
          }
        }
      ]
    }
  }, 
  "size": 10
}

精確查詢category_id為"xxxxxxxx"的文檔,取10條數據,不需要排序,不需要總數

總流程分3步:

客戶端發起請求到Node1

Node1作為協調節點,將請求轉發到索引的每個主分片或副分片中,每個分片在本地執行查詢。

每個節點返回各自的數據,協調節點匯總后返回給客戶端

如圖可以大致描繪這個過程:

2e9e6b4e-fb6b-11ed-90ce-dac502259ad0.png

我們知道ES是依賴Lucene提供的能力,真正的搜索發生在Lucene中,還需要繼續了解Lucene中的搜索過程。

(2)Lucene

Lucene中包含了四種基本數據類型,分別是:

Index:索引,由很多的Document組成。

Document:由很多的Field組成,是Index和Search的最小單位。

Field:由很多的Term組成,包括Field Name和Field Value。

Term:由很多的字節組成。一般將Text類型的Field Value分詞之后的每個最小單元叫做Term。

在介紹Lucene index的搜索過程之前,這里先說一下組成Lucene index的最小數據存儲單元——Segment。

Lucene index由許許多多的Segment組成,每一個Segment里面包含著文檔的Term字典、Term字典的倒排表、文檔的列式存儲DocValues以及正排索引。它能夠獨立的直接對外提供搜索功能,幾乎是一個縮小版的Lucene index。

(3)Term字典和倒排表

2ea8d714-fb6b-11ed-90ce-dac502259ad0.png

上圖是Term字典和其倒排表的大致樣子 當然這里還有些重要數據結構,比如:

FST:term索引,在內存中構建。可以快速實現單Term、Term范圍、Term前綴和通配符查詢。

BKD-Tree:用于數值類型(包括空間點)的快速查找。

SkipList:倒排表的數據結構

這里面的細節比較多,感興趣的可以單獨了解,這里不影響我們的整體搜索流程,不過多贅述。 有了Term字典和倒排表我們就能直接拿到搜索條件匹配的結果集了,接下來只需要通過docID去正排索引中取回整個doc然后返回就完事兒了。 這是ES的基本盤理論上不會慢,我們猜測慢查詢發生在排序上。那給請求加一個排序會發生什么呢?比如:

GET /content-alias/_search
{
  "track_total_hits":false,
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "category_id.keyword": "xxxxxxxx"
          }
        }
      ]
    }
  }, 
  "sort": [
    {
      "publish_time": {
        "order": "desc"
      }
    }
  ],
  "size": 10
}

通過倒排表拿到的docId是無序的,現在指定了排序字段,最簡單直接的辦法是全部取出來,然后排序取前10條。這樣固然能實現效果,但是效率卻是可想而知。那么Lucene是怎么解決的呢?

(4)DocValues

倒排索引能夠解決從詞到文檔的快速映射,但需要對檢索結果進行分類、排序、數學計算等聚合操作時需要文檔號到值的快速映射。而正排索引又過于臃腫龐大,怎么辦呢?

這時候各位大佬可能就直接想到了列式存儲,沒有錯,Lucene就引入了基于docId的列式存儲結構——DocValues

文檔號 列值 列值映射
0 2023-01-13 2
1 2023-01-12 1
2 2023-03-13 3

比如上表中的DocValues=[2023-01-13, 2023-01-12,2023-03-13]

如果列值是字符串,Lucene會把原來的字符串值按照字典排序生成數字ID,這樣的預處理能進一步加快排序速度。于是我們得到了DocValues=[2, 1, 3]

Docvalues的列式存儲形式可以加快我們的遍歷的速度。到這里一個常規的搜索取前N條記錄的請求算是真正的拆解完成。這里不討論詞頻、相關性打分、聚合等功能的分析,所以本文對整個過程和數據結構做了大幅簡化。如果對這部分感興趣,歡迎一起討論。

此時排序慢的問題也逐漸浮出了水面:盡管Docvalues又是列式存儲,又是將復雜值預處理為簡單值避免了查詢時的復雜比較,但是依舊架不住我們需要排序的數據集過大。

看起來ES盡力了,它好像確實不擅長解決我們這個場景的慢查詢問題。

不過有靈性的各位讀者肯定想到了,如果能把倒排表按照我們預先指定的順序存儲好,就能省下整個排序的時間

2.2.2 IndexSorting

很快ES官方文檔《How to tune for search speed》中提到了一個搜索優化手段——索引排序(Index Sorting)出現在了我們的視野中。

從文檔上的描述我們可以知道,索引排序對于搜索性能的提升主要在兩個方面:

對于多條件并列查詢(a and b and ...),索引排序可以幫助我們把不符合條件的文檔存在一起,跳過大量的不匹配的文檔。但是此技巧僅適用于經常用于篩選的低基數字段。

提前中斷:當搜索排序和索引排序指定的順序一樣時,只需要比較每個段的前 N 個文檔,其他的文檔僅需要用于總數計算。比如:我們的文檔中有一個時間戳,而我們經常需要按照時間戳來搜索和排序,這時候如果指定的索引排序和搜索排序一致,通常能夠極大的提高搜索排序的效率。

提前中斷!!!簡直是缺什么來什么,于是我們開始圍繞這一點展開調研。

(1)開啟索引排序

PUT /content
{
    "settings": {
        "index": {
            "sort.field": "publish_time", // 可指定多個字段
            "sort.order": "desc"
        }
    },
    "mappings": {
        "properties": {
            "content_id": {
                "type": "long"
            },
            "publish_time": {
                "type": "long"
            },
            ...
        }
    }
}
如上面的例子,文檔在寫入磁盤時會按照 publish_time 字段的遞減序進行排序。

在前面的段落中我們反復提到了docID和正排索引。這里我們順帶簡單介紹下他們的關系,首先Segment中的每個文檔,都會被分配一個docID,docID從0開始,順序分配。在沒有IndexSorting時,docID是按照文檔寫入的順序進行分配的,在設置了IndexSorting之后,docID的順序就與IndexSorting的順序一致。

下圖描述了docID和正排索引的關系:

2eb1e818-fb6b-11ed-90ce-dac502259ad0.png

那么再次回頭來看看我們最開始的查詢:

GET /content-alias/_search
{
  "track_total_hits":true,
  "sort": [
    {
      "publish_time": {
        "order": "desc"
      }
    }
  ],
  "size": 10
}

在Lucene中進行查詢時,發現結果集的倒排表順序剛好是publish_time降序排序的,所以查詢到前10條數據之后即可返回,這就做到了提前中斷,省下了排序開銷。那么代價是什么呢?

(2)代價

IndexSorting和查詢時排序不一樣,本質是在寫入時對數據進行預處理。所以排序字段只能在創建時指定且不可更改。并且由于寫入時要對數據進行排序,所以也會對寫入性能也會有一定負面影響。

之前我們提到了Lucene本身對排序也有各種優化,所以如果搜索結果集本身沒有那么多的數據,那么就算不開啟這個功能,也能有不錯的RT。

另外由于多數時候還是要計算總數,所以開啟索引排序之后只能提前中斷排序過程,還是要對結果集的總數進行count。如果能夠不查總數,或者說通過另外的方式獲取總數,那么能夠更好的利用這個特性。

小結:

針對大結果集的排序取前N條的場景下,索引排序能顯著提高搜索性能

索引排序只能在創建索引時指定,不可更改。如果你有多個指定字段排序的場景,可能需要慎重選擇排序字段。

不獲取總數能更好的利用索引排序

開啟索引排序會一定程度降低寫性能。這里貼一條ElaticsearchBenchmarks的數據截圖供大家參考。

2eb8df74-fb6b-11ed-90ce-dac502259ad0.png

見:Elasticsearch Benchmarks

2.3 效果

由于我們的業務遠遠沒有達到ES的寫入瓶頸,而且也少有頻繁變更排序字段的場景。在經過短暫的權衡之后,確定索引排序正是我們需要的,于是開始使用線上真實數據對索引排序的效果進行簡單的性能測試。

(1)性能測試:首頁

2ebe982e-fb6b-11ed-90ce-dac502259ad0.png

(2)性能測試:其他

這里開啟索引排序后,隨機幾個常規條件和時間窗口的搜索組合測試

2ec6dfe8-fb6b-11ed-90ce-dac502259ad0.png

可以看到效果非常明顯,沒有以前的那種尖刺,RT也很穩定,于是我們決定正式上線這個功能。

(3)線上效果

慢查詢

2ecf2d74-fb6b-11ed-90ce-dac502259ad0.png

整體前后對比

2ed93eea-fb6b-11ed-90ce-dac502259ad0.png

和我們預期的基本一樣,搜索RT大幅降低,慢查詢完全消失。

2.4后續優化

在探索過程中,其實還發現了一些其他的優化手段,鑒于開發成本和收益,有些我們并沒有完全應用于生產環境。這里列出其中幾點,希望能給大家一些啟發。

不獲取總數: 大部分場景下,不查詢總數都能減少開銷,提高性能。ES 7.x之后的搜索接口默認不返回總數了,由此可見一斑。

自定義routing規則: 從上文的查詢過程我們可以看到,ES會輪詢所有分片以獲取想要的數據,如果我們能控制數據的分片落點,那么也能節省不少開銷。比如說:如果我們將來如果有大量的場景都是查某個用戶的動態,那么可以控制按照用戶分片,這樣就避免了分片輪詢,也能提升搜索效率。

keyword: 不是所有的數字都應該按照數值字段來存,如果你的數字值很少用于范圍查詢,但是經常被用作term查詢,并且對搜索rt很敏感。那么keyword才是最適合的存儲方式。

數據預處理:就像IndexSoting一樣,如果我們能夠在寫入時預處理好數據,也能節省搜索時的開銷。這一點配合_ingest/pipeline 也許能發揮意想不到的效果。

3

寫在最后

相信看到這里的大家都能看出,我們的優化中也沒有涉及到十分高深的技術難點,我們只是在解決問題的過程中,逐步從小白轉變成了一個初學者。來一個大牛也許從一開始就能直接繞過我們的彎路,不過萬里之行始于足下,最后這里總結一點經驗和感受分享給大家,希望能給與我們一樣的初學者一些參考。

ES在大結果集指定字段排序的場景下性能不佳,我們使用時應該盡量避免出現這種場景。如果無法避免,合適的IndexSorting設置能大幅提升排序性能

審核編輯:彭靜
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 接口
    +關注

    關注

    33

    文章

    8497

    瀏覽量

    150834
  • 數據
    +關注

    關注

    8

    文章

    6892

    瀏覽量

    88827
  • 代碼
    +關注

    關注

    30

    文章

    4748

    瀏覽量

    68351

原文標題:億級ES數據搜索性能調優實踐

文章出處:【微信號:OSC開源社區,微信公眾號:OSC開源社區】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    HBase性能優化方法總結

    HBase是Hadoop生態系統中的一個組件,是一個分布式、面向列的開源數據庫,可以支持數百萬列、超過10行的數據存儲,因此,對HBase性能提出了一定的要求,那么如何進行HBase
    發表于 04-20 17:16

    優化了功率的20位1MSPS高性能數據采集系統

    描述該適用于高性能數據采集 (DAQ) 系統的參考設計優化了功率,以降低功耗并最大程度地減小開關穩壓器的 EMI 影響(通過使用 LMS3635-Q1 降壓轉換器)。與 LM5363
    發表于 12-05 13:56

    什么是探索性測試ET

    索性測試ET(exploratory)是和ST(script based test)相比較而言的.籠統地說,ST就是有確定的步驟和預期目標的測試.探索性測試可以說是一種測試思維。它沒有很多實際
    發表于 07-05 06:38

    數據庫設計及開發規范之sql性能優化

    數據庫設計及開發規范,sql性能優化
    發表于 05-08 10:58

    用BI系統做級數據分析,效率會變慢嗎?

    影響的報表格式要求,一鍵即可生成。同時,奧威BI的分布式計算,還能以低成本獲得大數據性能計算能力。即使涉及級數據的運算分析,也能夠保持秒
    發表于 02-07 13:52

    優化電動汽車的結構性能

    優化電動汽車的結構性能以提高效率和安全性迅速增長的全球電動汽車(EV)市場預計到2027年將達到8028美元。在電池和高壓電子設備的驅動下,電動汽車的運行和維護成本往往低于傳統汽車,幾乎不會產生
    發表于 09-17 08:10

    電路功耗優化的相關資料分享

    設計保持其性能,即滿足設計規則和時序的要求。功耗優化前的設計是已經映射到工藝庫的電路,如下圖所示:      門電路的功耗優化包括了設計總功耗,動態功耗以及漏電功耗的
    發表于 11-12 06:14

    基于興趣相關度的P2P網絡搜索優化算法

    P2P網絡中的搜索性能是影響P2P網絡發展的關鍵問題。該文研究非結構化分散型P2P網絡中的搜索機制,提出2個改進算法。改進算法利用節點的共享情況和查詢歷史發掘節點的興趣愛好
    發表于 04-21 09:51 ?15次下載

    Allegro封裝命名要注重可搜索性

    在封裝的命名上,特別是在pcb layout軟件allegro里面,封裝命名要注重可搜索性,pcb設計培訓這里說的可搜索性是指window對文件的排列,我們知道封裝在allegro里面里面以.dra結尾,如果零件
    發表于 06-25 11:36 ?4191次閱讀

    混合搜索的含邏輯“與”“或”的RM優化算法

    問題已有的解法包括函數變換、混合整數規劃、線性規劃搜索等算法.隨著任務數的增多,這些算法的求解時間較長.提出一種基于線性規劃的深度廣度混合搜索算法(LPHS),將廣義約束優化問題拆分成若干子問題建立線性規劃
    發表于 12-25 17:13 ?0次下載
    混合<b class='flag-5'>搜索</b>的含邏輯“與”“或”的RM<b class='flag-5'>優化</b>算法

    數據是如何優化企業搜索引擎

    企業網站將比以往任何時候都更多地使用大數據,大數據搜索引擎優化(SEO)中起著非常重要的作用。
    發表于 12-28 10:24 ?2228次閱讀

    支持向量機網絡搜索優化應用程序下載

    支持向量機網絡搜索優化應用程序下載
    發表于 04-20 09:51 ?0次下載

    傳統關系型數據庫和ES的差別

    上面。這個也是我在學習之前對 ES 最感興趣的部分。 本文大致包括以下內容: 關于搜索:傳統關系型數據庫和 ES 的差別 搜索引擎原理 細究
    的頭像 發表于 10-12 10:49 ?2501次閱讀

    如何提高數據倉庫的性能優化設計

      隨著數據倉庫規模的擴大,數據倉庫的性能問題就顯得越來越突出,如何提高數據倉庫的性能,除了在設計階段對其邏輯結構和物理結構進行
    發表于 07-18 16:10 ?0次下載

    如何優化emc存儲性能

    在當今的數據中心環境中,存儲性能對于業務連續性和數據訪問速度至關重要。EMC作為領先的存儲解決方案提供商,其產品線涵蓋了從入門到企業的存
    的頭像 發表于 11-01 15:57 ?202次閱讀