<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          干貨 | 全方位深度解讀 Elasticsearch 分頁(yè)查詢

          共 9948字,需瀏覽 20分鐘

           ·

          2021-05-11 09:27

          1、關(guān)于 Elasticsearch 分頁(yè)查詢,這幾個(gè)問(wèn)題經(jīng)常被問(wèn)到

          • 問(wèn)題1:想請(qǐng)問(wèn)下,一次性獲取索引上的某個(gè)字段的所有值(100 萬(wàn)左右),除了把 max_result_window 調(diào)大 ,還有沒(méi)有啥方法?

          • 問(wèn)題2:關(guān)于 es 的分頁(yè),每次拿 20 條展示在前臺(tái),然后點(diǎn)擊下一頁(yè),在查詢后面的20條數(shù)據(jù),應(yīng)該要怎么寫?

          • 問(wèn)題3:From+size、Scroll、search_after 的本質(zhì)區(qū)別和應(yīng)用場(chǎng)景分別是什么?

          2、 Elasticsearch 支持的三種分頁(yè)查詢方式

          • From + Size 查詢
          • Search After 查詢
          • Scroll 查詢

          下面我就三種方式的聯(lián)系與區(qū)別、優(yōu)缺點(diǎn)、適用場(chǎng)景等展開(kāi)進(jìn)行解讀。

          2.1 From + size 分頁(yè)查詢

          2.1.1 From + size 分頁(yè)查詢定義與實(shí)戰(zhàn)案例

          如下基礎(chǔ)查詢:

          GET kibana_sample_data_flights/_search

          默認(rèn)返回前10個(gè)匹配的匹配項(xiàng)。其中:

          • from:未指定,默認(rèn)值是 0,注意不是1,代表當(dāng)前頁(yè)返回?cái)?shù)據(jù)的起始值。
          • size:未指定,默認(rèn)值是 10,代表當(dāng)前頁(yè)返回?cái)?shù)據(jù)的條數(shù)。

          如下指定條件查詢和排序:

          GET kibana_sample_data_flights/_search
          {
            "from": 0,
            "size":20,
            "query": {
              "match": {
                "DestWeather""Sunny"
              }
            },
            "sort": [
              {
                "FlightTimeHour": {
                  "order""desc"
                }
              }
            ]
          }

          共返回 20 條數(shù)據(jù)。

          其中:from + size 兩個(gè)參數(shù)定義了結(jié)果頁(yè)面顯示數(shù)據(jù)的內(nèi)容。

          2.1.2 From + size 查詢優(yōu)缺點(diǎn)及適用場(chǎng)景

          From + size 查詢優(yōu)點(diǎn)

          • 支持隨機(jī)翻頁(yè)。

          From + size 查詢?nèi)秉c(diǎn)

          • 受制于 max_result_window 設(shè)置,不能無(wú)限制翻頁(yè)。

          • 存在深度翻頁(yè)問(wèn)題,越往后翻頁(yè)越慢。

          From + size 查詢適用場(chǎng)景

          第一:非常適合小型數(shù)據(jù)集或者大數(shù)據(jù)集返回 Top N(N <= 10000)結(jié)果集的業(yè)務(wù)場(chǎng)景。

          第二:類似主流 PC 搜索引擎(谷歌、bing、百度、360、sogou等)支持隨機(jī)跳轉(zhuǎn)分頁(yè)的業(yè)務(wù)場(chǎng)景。


          2.1.3 深度翻頁(yè)不推薦使用 From + size

          Elasticsearch 會(huì)限制最大分頁(yè)數(shù),避免大數(shù)據(jù)量的召回導(dǎo)致性能低下。

          Elasticsearch 的 max_result_window 默認(rèn)值是:10000。也就意味著:如果每頁(yè)有 10 條數(shù)據(jù),會(huì)最大翻頁(yè)至 1000 頁(yè)。

          實(shí)際主流搜索引擎都翻不了那么多頁(yè),舉例:百度搜索“上?!?,翻到第 76 頁(yè),就無(wú)法再往下翻頁(yè)了,提示信息如下截圖所示:

          如下的分頁(yè)查詢

          GET kibana_sample_data_flights/_search
          {
            "from": 0,
            "size":10001
          }

          GET kibana_sample_data_flights/_search
          {
            "from": 10001,
            "size":10
          }

          報(bào)錯(cuò)如下:

          {
            "error" : {
              "root_cause" : [
                {
                  "type" : "illegal_argument_exception",
                  "reason" : "Result window is too large, from + size must be less than or equal to: [10000] but was [10001]. See the scroll api for a more efficient way to request large data sets. This limit can be set by changing the [index.max_result_window] index level setting."
                }
              ],

          什么原因?超過(guò)了最大窗口的限制,index.max_result_window 默認(rèn)值為10000。

          報(bào)錯(cuò)信息還同時(shí)給出了兩個(gè)解決方案:

          • 方案一:大數(shù)據(jù)集召回?cái)?shù)據(jù)使用:scroll api。

          后面會(huì)詳細(xì)講解。

          • 方案二:調(diào)大 index.max_result_window 默認(rèn)值。
          PUT kibana_sample_data_flights/_settings
          {
              "index.max_result_window":50000
          }

          官方建議:避免過(guò)度使用 from 和 size 來(lái)分頁(yè)或一次請(qǐng)求太多結(jié)果。

          不推薦使用 from + size 做深度分頁(yè)查詢的核心原因:

          • 搜索請(qǐng)求通??缭蕉鄠€(gè)分片,每個(gè)分片必須將其請(qǐng)求的命中內(nèi)容以及任何先前頁(yè)面的命中內(nèi)容加載到內(nèi)存中。

          • 對(duì)于翻頁(yè)較深的頁(yè)面或大量結(jié)果,這些操作會(huì)顯著增加內(nèi)存和 CPU 使用率,從而導(dǎo)致性能下降或節(jié)點(diǎn)故障。

          什么意思呢?

          GET kibana_sample_data_flights/_search
          {
            "from": 10001,
            "size": 10
          }

          共 10 條數(shù)據(jù)加載到內(nèi)存嗎?不是的!

          共:10011 條數(shù)據(jù)加載到內(nèi)存,然后經(jīng)過(guò)后臺(tái)處理后返回了最后 10 條我們想要的數(shù)據(jù)。

          那也就意味著,越往后翻頁(yè)(也就是深度翻頁(yè))需要加載的數(shù)據(jù)量越大,勢(shì)必會(huì)越耗費(fèi) CPU + 內(nèi)存資源,響應(yīng)也會(huì)越慢!

          2.2 search_after 查詢

          2.2.1 search_after 查詢定義與實(shí)戰(zhàn)案例

          search_after 查詢本質(zhì):使用前一頁(yè)中的一組排序值來(lái)檢索匹配的下一頁(yè)。

          前置條件:使用 search_after 要求后續(xù)的多個(gè)請(qǐng)求返回與第一次查詢相同的排序結(jié)果序列。也就是說(shuō),即便在后續(xù)翻頁(yè)的過(guò)程中,可能會(huì)有新數(shù)據(jù)寫入等操作,但這些操作不會(huì)對(duì)原有結(jié)果集構(gòu)成影響。

          如何實(shí)現(xiàn)呢?

          可以創(chuàng)建一個(gè)時(shí)間點(diǎn) Point In Time(PIT)保障搜索過(guò)程中保留特定事件點(diǎn)的索引狀態(tài)。

          Point In Time(PIT)是 Elasticsearch 7.10 版本之后才有的新特性。

          PIT的本質(zhì):存儲(chǔ)索引數(shù)據(jù)狀態(tài)的輕量級(jí)視圖。

          如下示例能很好的解讀 PIT 視圖的內(nèi)涵。

          # 創(chuàng)建 PIT
          POST kibana_sample_data_logs/_pit?keep_alive=1m

          # 獲取數(shù)據(jù)量 14074
          POST kibana_sample_data_logs/_count

          # 新增一條數(shù)據(jù)
          POST kibana_sample_data_logs/_doc/14075
          {
            "test":"just testing"
          }

          # 數(shù)據(jù)總量為 14075
          POST kibana_sample_data_logs/_count


          # 查詢PIT,數(shù)據(jù)依然是14074,說(shuō)明走的是之前時(shí)間點(diǎn)的視圖的統(tǒng)計(jì)。
          POST /_search
          {
            "track_total_hits"true
            "query": {
              "match_all": {}
            }, 
             "pit": {
              "id""48myAwEXa2liYW5hX3NhbXBsZV9kYXRhX2xvZ3MWM2hGWXpxLXFSSGlfSmZIaXJWN0dxUQAWdG1TOWFMTF9UdTZHdVZDYmhoWUljZwAAAAAAAAEN3RZGOFJCMGVrZVNndTk3U1I0SG81V3R3AAEWM2hGWXpxLXFSSGlfSmZIaXJWN0dxUQAA"
            }
          }

          有了 PIT,search_after 的后續(xù)查詢都是基于 PIT 視圖進(jìn)行,能有效保障數(shù)據(jù)的一致性。

          search_after 分頁(yè)查詢可以簡(jiǎn)單概括為如下幾個(gè)步驟。

          步驟 1:創(chuàng)建 PIT 視圖,這是前置條件不能省。

          # Step 1: 創(chuàng)建 PIT
          POST kibana_sample_data_logs/_pit?keep_alive=5m

          返回結(jié)果如下:

          {
            "id" : "48myAwEXa2liYW5hX3NhbXBsZV9kYXRhX2xvZ3MWM2hGWXpxLXFSSGlfSmZIaXJWN0dxUQAWdG1TOWFMTF9UdTZHdVZDYmhoWUljZwAAAAAAAAEg5RZGOFJCMGVrZVNndTk3U1I0SG81V3R3AAEWM2hGWXpxLXFSSGlfSmZIaXJWN0dxUQAA"
          }

          keep_alive=5m,類似scroll的參數(shù),代表視圖保留時(shí)間是 5 分鐘,超過(guò) 5 分鐘執(zhí)行會(huì)報(bào)錯(cuò)如下:

            "type" : "search_context_missing_exception",
            "reason" : "No search context found for id [91600]"

          步驟 2:創(chuàng)建基礎(chǔ)查詢語(yǔ)句,這里要設(shè)置翻頁(yè)的條件。

          # Step 2: 創(chuàng)建基礎(chǔ)查詢
          GET /_search
          {
            "size":10,
            "query": {
              "match" : {
                "host" : "elastic"
              }
            },
            "pit": {
               "id":  "48myAwEXa2liYW5hX3NhbXBsZV9kYXRhX2xvZ3MWM2hGWXpxLXFSSGlfSmZIaXJWN0dxUQAWdG1TOWFMTF9UdTZHdVZDYmhoWUljZwAAAAAAAAEg5RZGOFJCMGVrZVNndTk3U1I0SG81V3R3AAEWM2hGWXpxLXFSSGlfSmZIaXJWN0dxUQAA"
               "keep_alive""1m"
            },
            "sort": [ 
              {"response.keyword""asc"}
            ]
          }
          • 設(shè)置了PIT,檢索時(shí)候就不需要再指定索引。

          • id 是基于步驟1 返回的 id 值。

          • 排序 sort 指的是:按照哪個(gè)關(guān)鍵字排序。

          在每個(gè)返回文檔的最后,會(huì)有兩個(gè)結(jié)果值,如下所示:

           "sort" : [
                    "200",
                    4
                  ]
          • 其中,“200”就是我們指定的排序方式:基于 {"response.keyword": "asc"} 升序排列。

          而 4 代表什么含義呢?

          • 4 代表——隱含的排序值,是基于_shard_doc 的升序排序方式。

          官方文檔把這種隱含的字段叫做:tiebreaker (決勝字段),tiebreaker 等價(jià)于_shard_doc。

          tiebreaker 本質(zhì)含義:每個(gè)文檔的唯一值,確保分頁(yè)不會(huì)丟失或者分頁(yè)結(jié)果數(shù)據(jù)出現(xiàn)重復(fù)(相同頁(yè)重復(fù)或跨頁(yè)重復(fù))。

          步驟3:實(shí)現(xiàn)后續(xù)翻頁(yè)。

          # step 3 : 開(kāi)始翻頁(yè)
          GET /_search
          {
            "size": 10,
            "query": {
              "match" : {
                "host" : "elastic"
              }
            },
            "pit": {
               "id":  "48myAwEXa2liYW5hX3NhbXBsZV9kYXRhX2xvZ3MWM2hGWXpxLXFSSGlfSmZIaXJWN0dxUQAWdG1TOWFMTF9UdTZHdVZDYmhoWUljZwAAAAAAAAEg5RZGOFJCMGVrZVNndTk3U1I0SG81V3R3AAEWM2hGWXpxLXFSSGlfSmZIaXJWN0dxUQAA"
               "keep_alive""1m"
            },
            "sort": [
              {"response.keyword""asc"}
            ],
            "search_after": [                                
              "200",
              4
            ]
          }

          后續(xù)翻頁(yè)都需要借助 search_after 指定前一頁(yè)的最后一個(gè)文檔的 sort 字段值。

          如下代碼所示:

            "search_after": [                                
              "200",
              4
            ]

          顯然,search_after 查詢僅支持向后翻頁(yè)。

          2.2.2 search_after 查詢優(yōu)缺點(diǎn)及適用場(chǎng)景

          search_after 優(yōu)點(diǎn)

          • 不嚴(yán)格受制于 max_result_window,可以無(wú)限制往后翻頁(yè)。

          ps:不嚴(yán)格含義:?jiǎn)未握?qǐng)求值不能超過(guò) max_result_window;但總翻頁(yè)結(jié)果集可以超過(guò)。

          search_after 缺點(diǎn)
          • 只支持向后翻頁(yè),不支持隨機(jī)翻頁(yè)。

          search_after 適用場(chǎng)景

          • 類似:今日頭條分頁(yè)搜索  https://m.toutiao.com/search

          不支持隨機(jī)翻頁(yè),更適合手機(jī)端應(yīng)用的場(chǎng)景。

          2.3 Scroll 遍歷查詢

          2.3.1 Scroll 遍歷查詢定義與實(shí)戰(zhàn)案例

          相比于 From + size 和 search_after 返回一頁(yè)數(shù)據(jù),Scroll API 可用于從單個(gè)搜索請(qǐng)求中檢索大量結(jié)果(甚至所有結(jié)果),其方式與傳統(tǒng)數(shù)據(jù)庫(kù)中游標(biāo)(cursor)類似。

          如果把  From + size 和 search_after 兩種請(qǐng)求看做近實(shí)時(shí)的請(qǐng)求處理方式,那么 scroll 滾動(dòng)遍歷查詢顯然是非實(shí)時(shí)的。數(shù)據(jù)量大的時(shí)候,響應(yīng)時(shí)間可能會(huì)比較長(zhǎng)。

          scroll 核心執(zhí)行步驟如下:

          步驟 1:指定檢索語(yǔ)句同時(shí)設(shè)置 scroll 上下文保留時(shí)間。

          實(shí)際上,scroll 已默認(rèn)包含了 search_after 的PIT 的視圖或快照功能。

          從 Scroll 請(qǐng)求返回的結(jié)果反映了發(fā)出初始搜索請(qǐng)求時(shí)索引的狀態(tài),類似在那一個(gè)時(shí)刻做了快照。隨后對(duì)文檔的更改(寫入、更新或刪除)只會(huì)影響以后的搜索請(qǐng)求。

          POST kibana_sample_data_logs/_search?scroll=3m
          {
            "size": 100,
            "query": {
              "match": {
                "host""elastic"
              }
            }
          }

          步驟 2:向后翻頁(yè)繼續(xù)獲取數(shù)據(jù),直到?jīng)]有要返回的結(jié)果為止。

          POST _search/scroll                                   
          {
            "scroll" : "3m",
            "scroll_id":"FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFkY4UkIwZWtlU2d1OTdTUjRIbzVXdHcAAAAAAAGmkBZ0bVM5YUxMX1R1Nkd1VkNiaGhZSWNn" 
          }

          scroll_id 值是步驟 1 返回的結(jié)果值。

          2.3.2 Scroll 遍歷查詢優(yōu)缺點(diǎn)及適用場(chǎng)景

              scroll 查詢優(yōu)點(diǎn)

          • 支持全量遍歷。

          ps:?jiǎn)未伪闅v的 size 值也不能超過(guò) max_result_window 大小。

              scroll 查詢?nèi)秉c(diǎn)

          • 響應(yīng)時(shí)間非實(shí)時(shí)。

          • 保留上下文需要足夠的堆內(nèi)存空間。

          scroll 查詢適用場(chǎng)景

          • 全量或數(shù)據(jù)量很大時(shí)遍歷結(jié)果數(shù)據(jù),而非分頁(yè)查詢。

          • 官方文檔強(qiáng)調(diào):不再建議使用scroll API進(jìn)行深度分頁(yè)。如果要分頁(yè)檢索超過(guò) Top 10,000+ 結(jié)果時(shí),推薦使用:PIT + search_after。

          3、小結(jié)

          • From+ size:需要隨機(jī)跳轉(zhuǎn)不同分頁(yè)(類似主流搜索引擎)、Top 10000 條數(shù)據(jù)之內(nèi)分頁(yè)顯示場(chǎng)景。

          • search_after:僅需要向后翻頁(yè)的場(chǎng)景及超過(guò)Top 10000 數(shù)據(jù)需要分頁(yè)場(chǎng)景。

          • Scroll:需要遍歷全量數(shù)據(jù)場(chǎng)景 。

          • max_result_window:調(diào)大治標(biāo)不治本,不建議調(diào)過(guò)大。

          • PIT:本質(zhì)是視圖。



          本文說(shuō)法有不嚴(yán)謹(jǐn)?shù)牡胤?,?span style="color: rgb(255, 76, 65);">官方文檔為準(zhǔn)。

          歡迎大家就自己的分頁(yè)實(shí)踐進(jìn)行留言討論。

          參考:

          1. https://coralogix.com/log-analytics-blog/how-to-optimize-your-elasticsearch-queries-using-pagination

          2. https://www.javatpoint.com/elasticsearch-pagination

          3. https://www.elastic.co/guide/en/elasticsearch/reference/7.12/paginate-search-results.html


          推薦:

          瀏覽 45
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲欧美一级 | 红桃视频一区二区三区四区五区在线视频 | 人人看人人舔 | 成人做爰www免费看视频网站 | 777奇米在线视频 |