ElasticSearch-ESの深いページング問題を解決する(カーソルscroll)
12527 ワード
ES深さのページングを避けるために、ページング(from&size)を使用して10000以降のデータをクエリーすることはできません.したがって、10000以降のデータをクエリーする場合は、ESが提供するscroll(カーソル)を使用してクエリーします.
取りページ数が大きいと仮定すると(奥行きページ)、20ページ目を要求すると、Elasticsearchはすべてのスライス上の1ページ目から20ページ目までのすべてのドキュメントを取り出し、並べ替えを行い、最終的にfrom後のsizeエントリの結果を最終的な戻り値としてとして取り出す.
16個のスライスがあると仮定すると、coordinate nodeがshards*(from+size)バーレコードにまとめる必要があります.すなわち、16*(20+10)レコードが必要になった後、グローバルソートを行う必要があります.
したがって、インデックスが非常に大きい(千万または億)場合、from+sizeを使用して深いページを作成することはできません.ページが深いほどOOMが容易になり、OOMでなくてもCPUとメモリリソースが消費されます.
従って、ESは、保護手段として
scrollカーソルの原理
scrollはリレーショナル・データベースのcursorとして理解できます.そのため、scrollはリアルタイム検索に適していません.群発などのバックグラウンド・バッチ・タスクに適しています.
scrollは具体的に初期化と遍歴の2つのステップに分けられます
初期化時に検索条件に合致するすべての検索結果をキャッシュし、スナップショットとして想像できる.
遍歴中、このスナップショットからデータを取得
すなわち、初期化後にインデックスの挿入、削除、更新データに対して遍歴結果に影響を与えることはない.
カーソルがパフォーマンスを向上させる理由は、深いページを作成すると、検索のたびに並べ替え直さなければならないため、非常に無駄です.scrollを使用すると、使用するデータを一度に並べ替えてバッチで取り出すので、from+sizeを使用するよりもです.
具体例
初期化
リクエスト
注意URLのsearchの後に
sizeサイズを指定できます.つまり、何回かのデータが返信されるたびに、データがないまで返信されると200が成功します.hitsのhitsは空のlist になります.
初期化時には、
request bodyは一般検索と同様であるため、初期化の過程でscroll設定カーソルオン時間を加えた以外は、一般検索と変わらない(クエリー条件を設定するには、前sizeペンのデータも返信する)
結果
データの遍歴
リクエスト
初期化から戻る
また、scrollリクエストを送信たびに、このscrollのオープン時間を再リフレッシュし、うっかりタイムアウトしてデータ取得が不完全になることを防止する.
結果を返す
データがないと空のhitsが回送され、この判断でデータ
scrollクエリーの最適化
一般的なシナリオでは、scrollは通常、ソートが必要な大きなデータを取得するために使用されますが、データ間のソート性は私たちにとって関係なく、すべてのデータが取り出せばよい場合があります.この場合、scrollを最適化することができます.
初期化
scrollのクリア
scrollをオンに設定すると、1つのscrollの生存時間が設定されますが、使い終わった後に手で閉じることができれば、リソースを早期に解放することができ、ESの負担
取りページ数が大きいと仮定すると(奥行きページ)、20ページ目を要求すると、Elasticsearchはすべてのスライス上の1ページ目から20ページ目までのすべてのドキュメントを取り出し、並べ替えを行い、最終的にfrom後のsizeエントリの結果を最終的な戻り値としてとして取り出す.
16個のスライスがあると仮定すると、coordinate nodeがshards*(from+size)バーレコードにまとめる必要があります.すなわち、16*(20+10)レコードが必要になった後、グローバルソートを行う必要があります.
したがって、インデックスが非常に大きい(千万または億)場合、from+sizeを使用して深いページを作成することはできません.ページが深いほどOOMが容易になり、OOMでなくてもCPUとメモリリソースが消費されます.
従って、ESは、保護手段として
index.max_result_window:10000
を用いる、すなわち、デフォルトfrom+sizeは10000を超えてはならない.このパラメータは動的に変更してもよいし、プロファイルで構成してもよいが、そうしないほうがよい.ESカーソルを用いてデータを取得すべきである.scrollカーソルの原理
scrollはリレーショナル・データベースのcursorとして理解できます.そのため、scrollはリアルタイム検索に適していません.群発などのバックグラウンド・バッチ・タスクに適しています.
scrollは具体的に初期化と遍歴の2つのステップに分けられます
初期化時に検索条件に合致するすべての検索結果をキャッシュし、スナップショットとして想像できる.
遍歴中、このスナップショットからデータを取得
すなわち、初期化後にインデックスの挿入、削除、更新データに対して遍歴結果に影響を与えることはない.
カーソルがパフォーマンスを向上させる理由は、深いページを作成すると、検索のたびに並べ替え直さなければならないため、非常に無駄です.scrollを使用すると、使用するデータを一度に並べ替えてバッチで取り出すので、from+sizeを使用するよりもです.
具体例
初期化
リクエスト
注意URLのsearchの後に
scroll=1m
を付けてrequest bodyに書くことはできません.1m
はこのカーソルが1分間を開いたままであることを示しています.sizeサイズを指定できます.つまり、何回かのデータが返信されるたびに、データがないまで返信されると200が成功します.hitsのhitsは空のlist になります.
初期化時には、
_scroll_id
に加えて、前の100ペン(size=100と仮定)のデータも返信する.request bodyは一般検索と同様であるため、初期化の過程でscroll設定カーソルオン時間を加えた以外は、一般検索と変わらない(クエリー条件を設定するには、前sizeペンのデータも返信する)
POST 127.0.0.1:9200/my_index/_search?scroll=1m
{
"query":{
"range":{
"createTime": {
"gte": 1522229999999
}
}
},
"size": 1000
}
結果
{
"_scroll_id": "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAfv5-FjNOamF0Mk1aUUhpUnU5ZWNMaHJocWcAAAAAAH7-gBYzTmphdDJNWlFIaVJ1OWVjTGhyaHFnAAAAAAB-_n8WM05qYXQyTVpRSGlSdTllY0xocmhxZwAAAAAAdsJxFmVkZTBJalJWUmp5UmI3V0FYc2lQbVEAAAAAAHbCcBZlZGUwSWpSVlJqeVJiN1dBWHNpUG1R",
"took": 2,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 84,
"max_score": 1,
"hits": [
{
"_index": "video1522821719",
"_type": "doc",
"_id": "84056",
"_score": 1,
"_source": {
"title": " ",
"createTime": 1522239744000
}
}
.99 data
]
}
}
を返します.データの遍歴
リクエスト
初期化から戻る
_scroll_id
を使用して要求が行われ、各要求は初期化中の未完了データを返し続け、_scroll_id
が返される.この_scroll_id
は変更される可能性があるため、要求ごとに前回の要求から戻る_scroll_id
を持つべきである._scroll_id
を返しますが、リクエストに入れたのはscroll_id
で、スペルが異なるです.また、scrollリクエストを送信たびに、このscrollのオープン時間を再リフレッシュし、うっかりタイムアウトしてデータ取得が不完全になることを防止する.
結果を返す
データがないと空のhitsが回送され、この判断でデータ
POST 127.0.0.1:9200/_search/scroll?scroll=1m
{
"scroll_id": "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAdsMqFmVkZTBJalJWUmp5UmI3V0FYc2lQbVEAAAAAAHbDKRZlZGUwSWpSVlJqeVJiN1dBWHNpUG1RAAAAAABpX2sWclBEekhiRVpSRktHWXFudnVaQ3dIQQAAAAAAaV9qFnJQRHpIYkVaUkZLR1lxbnZ1WkN3SEEAAAAAAGlfaRZyUER6SGJFWlJGS0dZcW52dVpDd0hB"
}
が遍歴完了したか否かを判断することができる.scrollクエリーの最適化
一般的なシナリオでは、scrollは通常、ソートが必要な大きなデータを取得するために使用されますが、データ間のソート性は私たちにとって関係なく、すべてのデータが取り出せばよい場合があります.この場合、scrollを最適化することができます.
初期化
_doc
を使用してsortを除去した結果、この実行の効率は最も速いが、データはソートされず、すべてのデータを取得したいシーン{
"_scroll_id": "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAdsMqFmVkZTBJalJWUmp5UmI3V0FYc2lQbVEAAAAAAHbDKRZlZGUwSWpSVlJqeVJiN1dBWHNpUG1RAAAAAABpX2sWclBEekhiRVpSRktHWXFudnVaQ3dIQQAAAAAAaV9qFnJQRHpIYkVaUkZLR1lxbnZ1WkN3SEEAAAAAAGlfaRZyUER6SGJFWlJGS0dZcW52dVpDd0hB",
"took": 2,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 84,
"max_score": null,
"hits": []
}
}
に適している.scrollのクリア
scrollをオンに設定すると、1つのscrollの生存時間が設定されますが、使い終わった後に手で閉じることができれば、リソースを早期に解放することができ、ESの負担
POST 127.0.0.1:9200/my_index/_search?scroll=1m
{
"query": {
"match_all" : {}
},
"sort": [
"_doc"
]
}
}
を低減することができます.