读取ES亿级数据效率问题

Scroll滚动查询

滚动查询(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倍。

分析:

  1. 在使用match_all查询时,搜索引擎会直接返回所有文档的查询结果,该结果较为轻量级,因此单次API响应时间较快
  2. 当您使用 range查询进行查询时,Elasticsearch 需要在每个文档中查找并匹配时间范围条件,如果数据集很大,则会导致搜索引擎耗时,从而导致单次API响应时间相对较慢。
  3. 数据量较大。使用 range 查询请求时,由于需要针对所有匹配查询条件范围的文档进行扫描处理,而数据总量巨大,如果没有适当的索引策略、搜索近似性过强、时间片过小或查询超时等原因都会造成CPU资源大量占用处理异常缓慢而导致API响应变慢。

这里非常容易出现误解,基于滚动查询原理,第一次查询生成一个快照,后续滚动基于快照查询。而总量数据为10亿,和总量数据3亿的快照滚动查询,应该后者效率会高,然而事实并非如此!

实际上,由于 Scroll API 的操作方式和原理,以及不同滚动查询之间的具体批处理大小、超时时间等参数设置可能会对结果产生影响。因此,仅从总数据量的角度比较两次查询可能不够准确。


解决方案:

将range时间段缩短,适当的调整单次返回数目size大小,

经过测试,range时间段缩减后,第一次查询总数据在一千万左右,后续滚动查询效率恢复至200ms左右,


总之,在使用滚动查询是,需要在合理的返回批处理大小、超时时间或其他相关参数之间寻找平衡点,以达到最优的性能和稳定性,同时,也需要对查询和过滤逻辑进行细致的设计与调整,以减少不必要的计算开销,并进一步提升性能。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值