当前位置:   article > 正文

读取ES亿级数据效率问题_亿级查询es

亿级查询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":""
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

优化逻辑:多节点处理

不使用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":""
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

优化结果多节点比单节点慢近二十倍


原因分析:

多节点查询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左右,


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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/672032
推荐阅读
相关标签
  

闽ICP备14008679号