整理:Elasticsearch 三種分頁方式

目錄

1、from + size 淺分頁

from/size的原理:

2、scroll 深分頁

scroll原理:

3、search_after 深分頁

search_after的原理:


1、from + size 淺分頁


"淺"分頁可以理解爲簡單意義上的分頁。它的原理很簡單,就是查詢前20條數據,然後截斷前10條,只返回10-20的數據。這樣其實白白浪費了前10條的查詢。

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


其中,from定義了目標數據的偏移值size定義當前返回的數目。默認from爲0,size爲10,即所有的查詢默認僅僅返回前10條數據。

在這裏有必要了解一下

 

from/size的原理:


因爲es是基於分片的,假設有5個分片,from=100,size=10。則會根據排序規則從5個分片中各取回100條數據數據,然後彙總成500條數據後選擇最後面的10條數據

做過測試,越往後的分頁,執行的效率越低。總體上會隨着from的增加,消耗時間也會增加。而且數據量越大,就越明顯!

from+size查詢在10000-50000條數據(1000到5000頁)以內的時候還是可以的,但是如果數據過多的話,就會出現深分頁問題。

2、scroll 深分頁


爲了解決上面的問題,elasticsearch提出了一個scroll滾動的方式。
scroll 類似於sql中的cursor,使用scroll,每次只能獲取一頁的內容,然後會返回一個scroll_id。根據返回的這個scroll_id可以不斷地獲取下一頁的內容,所以scroll並不適用於有跳頁的情景。

GET test_dev/_search?scroll=5m
{
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "age": 28
          }
        }
      ]
    }
  },
  "size": 10,
  "from": 0,
  "sort": [
    {
      "timestamp": {
        "order": "desc"
      },
      "_id": {
        "order": "desc"
      }
    }
  ]
}


scroll=5m表示設置scroll_id保留5分鐘可用(快照保存5分鐘)
使用scroll必須要將from設置爲0。
size決定後面每次調用_search搜索返回的數量
然後我們可以通過數據返回的_scroll_id讀取下一頁內容,每次請求將會讀取下10條數據,直到數據讀取完畢或者scroll_id保留時間截止:

GET _search/scroll
{
  "scroll_id": "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAJZ9Fnk1d......",
  "scroll": "5m"
}


注意:請求的接口不再使用索引名了,而是 _search/scroll,其中GET和POST方法都可以使用。

scroll刪除:
根據官方文檔的說法,scroll的搜索上下文會在scroll的保留時間截止後自動清除,但是我們知道scroll是非常消耗資源的,所以一個建議就是當不需要了scroll數據的時候,儘可能快的把scroll_id顯式刪除掉。

清除指定的scroll_id:

DELETE _search/scroll/DnF1ZXJ5VGhlbkZldGNo.....

清除所有的scroll:

DELETE _search/scroll/_all

scroll原理:

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


3、search_after 深分頁

 

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"
      }
    }
  ]
}

search_after的原理:

原理顯而易見:就是通過排序+上一頁的排序字段最後一個的值,查詢上一頁最後一個之後的document

比如上面的例子 按更新時間倒序,查詢小於 search_after裏的時間戳參數的 document,因爲時間戳可能會重複,所以必須有全局唯一的字段輔助,本例子使用字段: _id,時間戳一樣的按 _id字段倒序,只要有全局唯一的組件做輔助,就可以實現下一頁的分頁查詢


版權聲明:本文爲CSDN博主「zhexiao27」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/andybegin/article/details/83864171

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