赞
踩
滚动查询(Scroll)是ElasticSearch提供的一个用于遍历数据集合的机制。它允许客户端初始时只获取一部分数据,然后可以通过不断发送滚动请求来迭代获取剩余的数据,直到全部数据都被检索出为止。利用游标 cursor 来持续地从 Elasticsearch 中读取数据,实现逐页获取数据的效果
其原理是在第一次查询时生成一个快照,并将这个快照与一个唯一的id关联起来,这个id称为Scroll ID。当客户端使用这个Scroll ID进行下一次查询时,Elasticsearch会把Scroll ID对应的快照重新载入内存,并返回新的搜索结果。每次查询都会返回一小批数据,同一批数据中的文档id保持不变,可作为后续查询的游标cursor使用;同时返回一个更新过期时间的新Scroll ID。
每日定时同步ES数据,数据量4-40亿,读取数据后根据key做聚合,每次循环读取ES一万条数据,读取完聚合存储于内存容器中,全部读取完写入mysql中。
使用scroll读取,单次读取一万条数据时间为200ms左右,读取十亿数据加数据处理完需要十二小时左右,性能较差,需要优化
GET /index/_search?scroll=10s
{
"query": {
"match_all":{}
}
}
//上面请求会返回 _scroll_id字段供下面请求使用, 循环调用下面请求
GET /_search/scroll
{
"scroll":"2s",
"scroll_id":""
}
不使用match_all全量查询,使用3个节点处理,每个节点读取八小时数据,大约每台机器处理三分之一的数据,理论上性能提升近三倍
。
优化后查询DSL:
GET /index/_search?scroll=10s { "query": { "bool":{ "filter": { "range":{ "@timestamp": { "from":"00:00:00", "to":"08:00:00" } } } } } } //上面请求会返回 _scroll_id字段供下面请求使用, 循环调用下面请求 GET /_search/scroll { "scroll":"2s", "scroll_id":"" }
优化结果:多节点比单节点慢近二十倍
多节点查询ES部分数据,每个节点第一个请求获取数据量总数会更少,滚动查询总数据量更少,理论上应该更快。由于只调用一次带
query
查询的API,其余均是滚动查询,因此可以定位是每次滚动查询性能降低了。
经测试,单节点 match_all
查询下,滚动查询单次响应时间 200ms
左右一次读取一万条,多节点优化后 query range
,滚动查询单次响应时间 4.5s
一次读取一万条。性能降低20倍。
分析:
match_all
查询时,搜索引擎会直接返回所有文档的查询结果,该结果较为轻量级,因此单次API响应时间较快range
查询进行查询时,Elasticsearch 需要在每个文档中查找并匹配时间范围条件,如果数据集很大,则会导致搜索引擎耗时,从而导致单次API响应时间相对较慢。这里非常容易出现误解,基于滚动查询原理,第一次查询生成一个快照,后续滚动基于快照查询。而总量数据为10亿,和总量数据3亿的快照滚动查询,应该后者效率会高,然而事实并非如此!
实际上,由于 Scroll API 的操作方式和原理,以及不同滚动查询之间的具体批处理大小、超时时间等参数设置可能会对结果产生影响。因此,仅从总数据量的角度比较两次查询可能不够准确。
将range时间段缩短,适当的调整单次返回数目size大小,
经过测试,range时间段缩减后,第一次查询总数据在一千万左右,后续滚动查询效率恢复至200ms
左右,
总之,在使用滚动查询是,需要在合理的返回批处理大小、超时时间或其他相关参数之间寻找平衡点,以达到最优的性能和稳定性,同时,也需要对查询和过滤逻辑进行细致的设计与调整,以减少不必要的计算开销,并进一步提升性能。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。