ElasticSearch分頁方案

1:from + size 淺分頁

"淺"分頁是最簡單的分頁方案眼刃。es會根據查詢條件在每一個DataNode分片中取出from+size條文檔舶斧,然后在MasterNode中聚合负芋、排序消别,再截取size-from的文檔返回給調用方算柳。當頁數(shù)越靠后低淡,也就是from+size越大,es需要讀取的數(shù)據也就是越大瞬项,聚合和排序的時候處理的數(shù)據量也越大蔗蹋,此時會加大服務器CPU和內存的消耗。


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

其中囱淋,from定義了目標數(shù)據的偏移值纸颜,size定義當前返回的數(shù)目。默認from為0绎橘,size為10胁孙,即所有的查詢默認僅僅返回前10條數(shù)據。

在這里有必要了解一下from/size的原理:

因為es是基于分片的称鳞,假設有5個分片涮较,from=100,size=10冈止。則會根據排序規(guī)則從5個分片中各取回100條數(shù)據數(shù)據狂票,然后匯總成500條數(shù)據后選擇最后面的10條數(shù)據。

做過測試熙暴,越往后的分頁闺属,執(zhí)行的效率越低慌盯。總體上會隨著from的增加掂器,消耗時間也會增加亚皂。而且數(shù)據量越大,就越明顯国瓮!

2:scroll 深分頁

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

為了解決上面的問題禁漓,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分鐘可用磷支。

使用scroll必須要將from設置為0谒撼。

size決定后面每次調用_search搜索返回的數(shù)量

然后我們可以通過數(shù)據返回的_scroll_id讀取下一頁內容,每次請求將會讀取下10條數(shù)據雾狈,直到數(shù)據讀取完畢或者scroll_id保留時間截止:


GET _search/scroll

{

  "scroll_id": "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAJZ9Fnk1d......",

  "scroll": "5m"

}

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

scroll刪除

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

清除指定的scroll_id:

DELETE _search/scroll/DnF1ZXJ5VGhlbkZldGNo.....

清除所有的scroll:

DELETE _search/scroll/_all

3:search_after 深分頁

scroll 的方式咒循,官方的建議不用于實時的請求(一般用于數(shù)據導出)据途,因為每一個 scroll_id 不僅會占用大量的資源,而且會生成歷史快照叙甸,對于數(shù)據的變更不會反映到快照上颖医。

search_after 分頁的方式是根據上一頁的最后一條數(shù)據來確定下一頁的位置,同時在分頁請求的過程中裆蒸,如果有索引數(shù)據的增刪改查熔萧,這些變更也會實時的反映到游標上。但是需要注意,因為每一頁的數(shù)據依賴于上一頁最后一條數(shù)據佛致,所以無法跳頁請求贮缕。

為了找到每一頁最后一條數(shù)據,每個文檔必須有一個全局唯一值俺榆,官方推薦使用 _uid 作為全局唯一值感昼,其實使用業(yè)務層的 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作為唯一值排序抑诸。

我們在返回的最后一條數(shù)據里拿到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"

      }

    }

  ]

}

4:修改默認分頁限制值10000

可以使用下面的方式來改變ES默認深度分頁的index.max_result_window 最大窗口值

curl -XPUT http://127.0.0.1:9200/my_index/_settings -d '{ "index" : { "max_result_window" : 500000}}'

其中my_index為要修改的index名爹殊,500000為要調整的新的窗口數(shù)。將該窗口調整后奸绷,便可以解決無法獲取到10000條后數(shù)據的問題梗夸。

注意事項

通過上述的方式解決了我們的問題,但也引入了另一個需要我們注意的問題号醉,窗口值調大了后反症,雖然請求到分頁的數(shù)據條數(shù)更多了,但它是用犧牲更多的服務器的內存畔派、CPU資源來換取的铅碍。要考慮業(yè)務場景中過大的分頁請求,是否會造成集群服務的OutOfMemory問題线椰。

5:獲取總數(shù)據量

修改最大限制值之后確實可以使from+size查詢到更后面頁的數(shù)據胞谈,但是每次查詢得到的總數(shù)量最大任然是10000,要想獲取大于1萬的查詢數(shù)據量憨愉,可以分兩步查詢烦绳,第一步使用scroll查詢獲取總數(shù)據量;第二部使用from+size查詢每頁的數(shù)據配紫,并設置分頁径密。這樣即解決了from+size無法查詢10000之后的數(shù)據,也解決了scroll無法跳頁的問題躺孝。

使用scroll可能遇到的問題:

Caused by: org.elasticsearch.ElasticsearchException: Trying to create too many scroll contexts. Must be less than or equal to: [500]. This limit can be set by changing the [search.max_open_scroll_context] setting.

這個報錯是從es的日志文件中查出來的享扔,大致意思是:嘗試創(chuàng)建更多的scroll對象失敗了,scroll對象總數(shù)量應該控制在500以內植袍【迕撸可修改search.max_open_scroll_context的值來改變500這個閾值。

原因:通過scroll 深分頁可知道奋单,es服務端會在內存中生成一個scroll_id對象锉试,并會為該值指定過期時間窘奏,翻頁的時候使用scroll_id來獲取下一頁的數(shù)據。默認情況下一姿,一個實例下面僅可以創(chuàng)建最多500個scroll上下文對象那伐,也就是500個scroll_id。報此錯誤的原因就是創(chuàng)建scroll上下文對象失敗应又,因為當前已經存在500個這樣的對象了宙项。

解決辦法:

1:通過觀察可以發(fā)現(xiàn),即使不做任何的處理株扛,過一會就又可以發(fā)起scroll請求了尤筐,這是因為時間超過了scroll生命周期時間,scroll對象自己死掉了一些洞就。

2:按照提示說的盆繁,修改search.max_open_scroll_context的值

put http://{{es-host}}/_cluster/settings

{

"persistent": {

    "search.max_open_scroll_context": 5000

},

"transient": {

    "search.max_open_scroll_context": 5000

}

}

[圖片上傳失敗...(image-4dc354-1583253824871)]

image.png

3:在使用完scroll_id之后立即調用刪除接口,刪除該scroll對象

刪除單個scroll

DELETE http://{{es-host}}/_search/scroll

{

"scroll_id": "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAdsMqFmVkZTBJalJWUmp5UmI3V0FYc2lQbVEAAAAAAHbDKRZlZGUwSWpSVlJqeVJiN1dBWHNpUG1RAAAAAABpX2sWclBEekhiRVpSRktHWXFudnVaQ3dIQQAAAAAAaV9qFnJQRHpIYkVaUkZLR1lxbnZ1WkN3SEEAAAAAAGlfaRZyUER6SGJFWlJGS0dZcW52dVpDd0hB"

}

刪除所有scroll

delete http://{{es-host}}/_search/scroll/_all

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末旬蟋,一起剝皮案震驚了整個濱河市油昂,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌倾贰,老刑警劉巖冕碟,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異匆浙,居然都是意外死亡安寺,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進店門首尼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來挑庶,“玉大人,你說我怎么就攤上這事饰恕∧痈幔” “怎么了?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵埋嵌,是天一觀的道長破加。 經常有香客問我,道長雹嗦,這世上最難降的妖魔是什么范舀? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮了罪,結果婚禮上锭环,老公的妹妹穿的比我還像新娘。我一直安慰自己泊藕,他們只是感情好辅辩,可當我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般玫锋。 火紅的嫁衣襯著肌膚如雪蛾茉。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天撩鹿,我揣著相機與錄音谦炬,去河邊找鬼。 笑死节沦,一個胖子當著我的面吹牛键思,可吹牛的內容都是我干的。 我是一名探鬼主播甫贯,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼吼鳞,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了获搏?” 一聲冷哼從身側響起赖条,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤失乾,失蹤者是張志新(化名)和其女友劉穎常熙,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體碱茁,經...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡裸卫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了纽竣。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片墓贿。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖蜓氨,靈堂內的尸體忽然破棺而出聋袋,到底是詐尸還是另有隱情,我是刑警寧澤穴吹,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布幽勒,位于F島的核電站,受9級特大地震影響港令,放射性物質發(fā)生泄漏啥容。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一顷霹、第九天 我趴在偏房一處隱蔽的房頂上張望咪惠。 院中可真熱鬧,春花似錦淋淀、人聲如沸遥昧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽炭臭。三九已至叫乌,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間徽缚,已是汗流浹背憨奸。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留凿试,地道東北人排宰。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像那婉,于是被迫代替她去往敵國和親板甘。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,627評論 2 350