ElasticSearch深さページングソリューション
15267 ワード
一般的な深さページング方式from+size
Esのデフォルトのページング方式はfrom+sizeの形式であり、深さページングの場合、この使用方式の効率は非常に低い.例えば、
from=5000、size=10、esは各スライスに並べ替えて5000*10個の有効データを得、結果セットから最後の10個を取る必要がある.
データはmongoのskip+sizeに似ています.
効率的な問題に加えて、esが現在サポートしている最大skip値はmax_です.result_Windows、デフォルト
10,000です.つまりfrom+size>max_result_Windowsの場合、esはエラーを返します
[root@dnsserver ~]# curl -XGET 127.0.0.1:9200/custm/_settings?pretty
{
"custm" : {
"settings" : {
"index" : {
"max_result_window" : "50000",
....
}
}
}
}
最初はオンラインのお客様のesデータに問題が発生し、数百ページに分割するとesはデータを返すことができません.このとき、正常な使用を回復するために、max_result_Windowsの値は50000に調整されます.
[root@dnsserver ~]# curl -XPUT "127.0.0.1:9200/custm/_settings" -d
'{
"index" : {
"max_result_window" : 50000
}
}'
そしてこの方法は一時的に問題を解決するしかなく、esの使用が多くなり、データ量が大きくなり、深さのページ分けのシーンが複雑になった場合、どのようにこの問題を解決しますか?
別のページング方式scroll
深さページングのシーンを満たすために、esはscroll方式でページング読み取りを提供する.原理的には、あるクエリに対してカーソルscroll_を生成します.id,後続のクエリは,結果セットで返されるhitsフィールドが空になるまで,このカーソルに基づいてデータを取得するだけで遍歴が終了することを示す.scroll_idの生成は,一時的な履歴スナップショットを確立したものと理解でき,その後の添削改ざんなどの操作はこのスナップショットの結果に影響を及ぼさない.
curlを使用してページングの読み込み手順は、次のとおりです.
[root@dnsserver ~]# curl -XGET 200.200.107.232:9200/product/info/_search?pretty&scroll=2m -d
'{"query":{"match_all":{}}, "sort": ["_doc"]}'
#
{
"_scroll_id": "cXVlcnlBbmRGZXRjaDsxOzg3OTA4NDpTQzRmWWkwQ1Q1bUlwMjc0WmdIX2ZnOzA7",
"took": 1,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"hits":{...}
}
[root@dnsserver ~]# curl -XGET '200.200.107.232:9200/_search/scroll?scroll=1m&scroll_id=cXVlcnlBbmRGZXRjaDsxOzg4NDg2OTpTQzRmWWkwQ1Q1bUlwMjc0WmdIX2ZnOzA7'
#
{
"_scroll_id": "cXVlcnlBbmRGZXRjaDsxOzk1ODg3NDpTQzRmWWkwQ1Q1bUlwMjc0WmdIX2ZnOzA7",
"took": 106,
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"hits": {
"total": 22424,
"max_score": 1.0,
"hits": [{
"_index": "product",
"_type": "info",
"_id": "did-519392_pdid-2010",
"_score": 1.0,
"_routing": "519392",
"_source": {
....
}
}
]
}
}
## srcoll_id
[root@dnsserver ~]# curl -XDELETE 127.0.0.1:9200/_search/scroll -d
'{"scroll_id" : ["cXVlcnlBbmRGZXRjaDsxOzg3OTA4NDpTQzRmWWkwQ1Q1bUlwMjc0WmdIX2ZnOzA7"]}'
## scroll_id
[root@dnsserver ~]# curl -XDELETE 127.0.0.1:9200/_search/scroll/_all
## scroll
[root@dnsserver ~]# curl -XGET 127.0.0.1:9200/_nodes/stats/indices/search?pretty
{
"cluster_name" : "200.200.107.232",
"nodes" : {
"SC4fYi0CT5mIp274ZgH_fg" : {
"timestamp" : 1514346295736,
"name" : "200.200.107.232",
"transport_address" : "200.200.107.232:9300",
"host" : "200.200.107.232",
"ip" : [ "200.200.107.232:9300", "NONE" ],
"indices" : {
"search" : {
"open_contexts" : 0,
"query_total" : 975758,
"query_time_in_millis" : 329850,
"query_current" : 0,
"fetch_total" : 217069,
"fetch_time_in_millis" : 84699,
"fetch_current" : 0,
"scroll_total" : 5348,
"scroll_time_in_millis" : 92712468,
"scroll_current" : 0
}
}
}
}
}
scroll + scan
scrollのドキュメントをソートする必要がない場合、esは検索の効率を高めるために、2.0バージョンでscroll+scanの方法を提供します.その後、2.1.0バージョンでscanの使用が削除され、この最適化がscrollに直接組み込まれました.moaラインのesバージョンは2.3なので、簡単に述べるだけです.使用するscanの方法はsearch_を指定することですtype=scan
# 2.0-beta scroll ,
[root@dnsserver ~]# curl '127.0.0.1:9200/order/info/_search?scroll=1m&search_type=scan' -d '{"query":{"match_all":{}}'
search_アフタ方式
上記のscroll searchの方法では、各scroll_idは、大量のリソース(特にソート要求)を占有するだけでなく、生成された履歴スナップショットであり、データの変更はスナップショットに反映されません.この方法は、データの移行やインデックスの変更など、大量のデータを非リアルタイムで処理する場合によく使用されます.では、リアルタイムで深さページングの問題を処理するとしたら?Esはsearch_を与えたafter方式では、>=5.0バージョンでのみ提供される機能です.
search_afterのページング方法とscrollにはいくつかの顕著な違いがあります.まず、前のページの最後のデータに基づいて次のページの位置を決定します.また、ページング要求の過程で、インデックスデータの削除変更があれば、これらの変更もカーソルにリアルタイムで反映されます.
各ページの最後のデータを見つけるには、各ドキュメントにグローバル一意の値が必要です.このページング方式は、現在のmoaメモリでrbtreeページングを使用する原理と同様に、公式に推奨されています.uidはグローバル一意の値として、実際にはビジネス層のidを使用してもよい.
curl -XGET 127.0.0.1:9200/order/info/_search
{
"size": 10,
"query": {
"term" : {
"did" : 519390
}
},
"sort": [
{"date": "asc"},
{"_uid": "desc"}
]
}
curl -XGET 127.0.0.1:9200/order/info/_search
{
"size": 10,
"query": {
"term" : {
"did" : 519390
}
},
"search_after": [1463538857, "tweet#654323"],
"sort": [
{"date": "asc"},
{"_uid": "desc"}
]
}
まとめ:search_afterは、各ページのデータが前のページの最後のデータに依存するため、ページ要求をスキップできない深さページング+ソートに適しています.
また、常に最新のデータが返され、ページング中にデータの位置が変更される可能性があります.このページング方式はmoaのビジネスシーンにもっと合っている.
Esライブラリscroll searchの実装
現在のサービス側のesバージョンは2.3に限られているため、より効率的なsearch_は使用できません.afterの方式は、一部のシーンではすべてのデータを取得するためにscrollの方式しか使用できません.以下はscroll_に基づくsearch実装のc API:
es_cursor * co_es_scroll_search(char* esindex, char* estype,
cJSON* query, cJSON* sort, cJSON* fields, int size, char* routing);
BOOL es_scroll_cursor_next(es_cursor* cursor);
void es_cursor_destroy(es_cursor* cursor);
具体的な業務の使用シーンは以下の通りである.
// 1. scroll_id
es_cursor *cursor = co_es_scroll_search((char*)index_name,(char*)type_name,
queryJ, sortJ, fieldJ, size , routing);
// 2. , scroll_id ,
while (es_scroll_cursor_next(cursor))
{
cJSON* data = es_cursor_json(cursor); //
....
}
// 3. , scroll_id ,
es_cursor_destroy(cursor);
添付:esバージョン変更記録は以下の通りです.
2.0 -> 2.1 -> 2.2 -> 2.3 -> 2.4 -> 5.0 -> 5.1 -> 5.2 -> 5.3 -> 5.4 -> 5.5 -> 5.6 -> 6.0 -> 6.1