elasticsearch深度分頁索引

原文鏈接:https://blog.csdn.net/wang_kill/article/details/88692207

背景:es 深度分頁索引效率問題

 

1.常見深度分頁方式 from+size

es 默認採用的分頁方式是 from+ size 的形式,在深度分頁的情況下,這種使用方式效率是非常低的,比如

from = 5000, size=10000, es 需要在各個分片上匹配排序並得到5000*10000條有效數據,然後在結果集中取最後10000條

數據返回.

除了效率上的問題,還有一個無法解決的問題是,es 目前支持最大的 skip 值是 max_result_window ,默認

爲  10000。也就是當 from + size > max_result_window 時,es 將返回錯誤.

當然,我們可以採用緊急規避方案,就是調整 max_result_window 的值。

curl -XPUT "127.0.0.1:9200/custm/_settings" -d '{ "index" : { "max_result_window" : 50000 } }'

然後這種方式只能暫時解決問題,當es 的使用越來越多,數據量越來越大,深度分頁的場景越來越複雜時,如何解決這種問題呢?
2.scroll 分頁方式

爲了滿足深度分頁的場景,es 提供了 scroll 的方式進行分頁讀取。原理上是對某次查詢生成一個遊標 scroll_id , 後續的查詢只需要根據這個遊標去取數據,直到結果集中返回的 hits 字段爲空,就表示遍歷結束。

scroll_id 的生成可以理解爲建立了一個臨時的歷史快照,在此之後的增刪改查等操作不會影響到這個快照的結果。

   1.先獲取第一個 scroll_id,url 參數包括 /index/_type/ 和 scroll,scroll 字段指定了scroll_id 的有效生存期,以分鐘爲單位,過期之後會被es 自動清理。

curl -XGET 127.0.0.1:9200/db/info/_search?pretty&scroll=2m -d '{"query":{"match_all":{}}, "sort": ["_doc"]}'

   2.後續讀取上一次查詢返回的scroll_id 來不斷的取下一頁,如果srcoll_id 的生存期很長,那麼每次返回的 scroll_id 都是一樣的,直到該 scroll_id 過期,纔會返回一個新的 scroll_id。請求指定的 scroll_id 時就不需要 /index/_type 等信息了。每讀取一頁都會重新設置 scroll_id 的生存時間,所以這個時間只需要滿足讀取當前頁就可以,不需要滿足讀取所有的數據的時間,1 分鐘足以。

curl -XGET '127.0.0.1:9200/_search/scroll?scroll=1m&scroll_id=cXDFERDGD45WEsdfd35DFEFDFX2ZnOzA

   3.所有文檔獲取完畢之後,需要手動清理掉 scroll_id 。雖然es 會有自動清理機制,但是 srcoll_id 的存在會耗費大量的資源來保存一份當前查詢結果集映像,並且會佔用文件描述符。所以用完之後要及時清理。使用 es 提供的 CLEAR_API 來刪除指定的 scroll_id

刪除掉所有索引上的 scroll_id    curl -XDELETE 127.0.0.1:9200/_search/scroll/_all

刪掉指定的多個  srcoll_id           curl -XDELETE 127.0.0.1:9200/_search/scroll -d '{"scroll_id" : ["cXDFERDGD45WEsdfd35DFEFDFX2ZnOzA"]}'
3.search_after 的方式

上述的 scroll search 的方式,官方的建議並不是用於實時的請求,因爲每一個 scroll_id 不僅會佔用大量的資源(特別是排序的請求),而且是生成的歷史快照,對於數據的變更不會反映到快照上。這種方式往往用於非實時處理大量數據的情況,比如要進行數據遷移或者索引變更之類的。那麼在實時情況下如果處理深度分頁的問題呢?es 給出了 search_after 的方式,這是在 >= 5.0 版本才提供的功能。

search_after 分頁的方式和 scroll 有一些顯著的區別,首先它是根據上一頁的最後一條數據來確定下一頁的位置,同時在分頁請求的過程中,如果有索引數據的增刪改查,這些變更也會實時的反映到遊標上。

爲了找到每一頁最後一條數據,每個文檔必須有一個全局唯一值,這種分頁方式其實和目前 moa 內存中使用rbtree 分頁的原理一樣,官方推薦使用 _uid 作爲全局唯一值,其實使用業務層的 id 也可以。
     第一頁的請求和正常的請求一樣

    curl -XGET 127.0.0.1:9200/db/info/_search

   {
    "size": 10,
    "query": {
        "term" : {
            "did" : 333
        }
    },
    "sort": [
        {"createdate": "asc"},
        {"_uid": "desc"}
    ]
}
     第二頁的請求,使用第一頁返回結果的最後一個數據的值,加上 search_after 字段來取下一頁。注意,使用 search_after 的時候要將 from 置爲 0 或 -1

curl -XGET 127.0.0.1:9200/order/info/_search
{
    "size": 10,
    "query": {
        "term" : {
            "did" : 333
        }
    },
    "search_after": [1463533345, "2039488283-ALT"],
    "sort": [
        {"createdate": "asc"},
        {"_uid": "desc"}
    ]
}

總結:search_after 適用於深度分頁+ 排序,因爲每一頁的數據依賴於上一頁最後一條數據,所以無法跳頁請求。
---------------------
作者:nb009網
來源:CSDN
原文:https://blog.csdn.net/wang_kill/article/details/88692207
版權聲明:本文爲博主原創文章,轉載請附上博文鏈接!

 

 

備註:參考:https://blog.csdn.net/andybegin/article/details/83864171 這篇文章提到,使用search_after 方式時,必須要設置from=0。

 

search_after 深分頁

scroll 的方式,官方的建議不用於實時的請求(一般用於數據導出),因爲每一個 scroll_id 不僅會佔用大量的資源,而且會生成歷史快照,對於數據的變更不會反映到快照上。

search_after 分頁的方式是根據上一頁的最後一條數據來確定下一頁的位置,同時在分頁請求的過程中,如果有索引數據的增刪改查,這些變更也會實時的反映到遊標上。但是需要注意,因爲每一頁的數據依賴於上一頁最後一條數據,所以無法跳頁請求。

爲了找到每一頁最後一條數據,每個文檔必須有一個全局唯一值,官方推薦使用 _uid 作爲全局唯一值,其實使用業務層的 id 也可以。

GET test_dev/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "age": 28
          }
        }
      ]
    }
  },
  "size": 20,
  "from": 0,
  "sort": [
    {
      "timestamp": {
        "order": "desc"
      },
      "_id": {
        "order": "desc"
      }
    }
  ]
}

    使用search_after必須要設置from=0。
    這裏我使用timestamp和_id作爲唯一值排序。
    我們在返回的最後一條數據裏拿到sort屬性的值傳入到search_after。

使用sort返回的值搜索下一頁:

GET test_dev/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "age": 28
          }
        }
      ]
    }
  },
  "size": 10,
  "from": 0,
  "search_after": [
    1541495312521,
    "d0xH6GYBBtbwbQSP0j1A"
  ],
  "sort": [
    {
      "timestamp": {
        "order": "desc"
      },
      "_id": {
        "order": "desc"
      }
    }
  ]
}


---------------------
作者:zhexiao27
來源:CSDN
原文:https://blog.csdn.net/andybegin/article/details/83864171
版權聲明:本文爲博主原創文章,轉載請附上博文鏈接!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章