es深分页的问题

232 阅读2分钟

@TOC

es深分页的问题解决

背景

公司es因为容量的原因,一般日志只存储7天。对于一些日志检索要求高一点的项目,可以发流程延长索引过期时间。但是这次碰见一个项目,需要日志保存3个月,而且日志的量级不小。鉴于此项目的特殊性,或者说为了解决此类特殊需求。暂定一个将指定es日志转存到hbase上。

es的基础概念

版本 7.X es

数据库和es概念对比

Relational DB	     Elasticsearch
数据库(database)	 索引(indices)
表(tables)	         types
行(rows)	         documents
字段(columns)	     fields

常用翻页

1、from size

浅分页情况下,可以考虑使用,因为是批量操作已有数据的日志转换,实测发现性能很差

2、Scroll

基于历史快照和上一页的scroll_id,查询下一页,实测scrollId 在翻页比较多的时候,会出现丢失的情况。导致记录不是完整有序的

3、Search After

本次采用的方法 1、适合顺序的从头往下分页 2、没有跳页的需求 3、占用内存少

4、游标的方式

这种方式没有深究。 使用游标方式存储状态: 在应用层,使用游标方式来存储状态,而不是依赖 Elasticsearch 来存储状态。通过这种方式,可以将搜索结果按批次获取,并存储游标以跟踪搜索状态。这样可以将搜索过程分解为多个较小的请求,并且减少深度翻页的需求。

深度翻页的问题

性能开销: 深度翻页可能导致性能开销增加,特别是当从大量数据中获取更多结果时。每次翻页都需要进行数据检索和排序,可能会影响搜索请求的响应时间。

资源消耗: 大量的深度翻页请求会消耗大量的服务器资源,包括 CPU、内存和网络带宽。

稳定性: 对于大数据集的深度翻页请求,可能会增加节点的负载,可能导致集群的不稳定性或性能下降。

结果变化: 在进行深度翻页时,如果数据集正在更新或有新的数据插入,可能导致结果的变化。这是因为 Elasticsearch 的分布式特性可能导致数据的一致性问题

Search After的实现

// Search After
    SearchRequest searchRequest = new SearchRequest(index);
    searchRequest.source(SearchSourceBuilder.searchSource()
            .size(transConfig.getBatchCount())
            .fetchSource(new String[]{"data", "timestamp", "application","className"}, null)
            .timeout(TimeValue.timeValueSeconds(1200))
            .sort("_doc", SortOrder.ASC));

将上一轮结果的最后一个值放到这里

    searchRequest.source(SearchSourceBuilder.searchSource()
            .size(transConfig.getBatchCount())
            .fetchSource(new String[]{"data", "timestamp", "application","className"}, null)
            .timeout(TimeValue.timeValueSeconds(1200))
            .sort("_doc", SortOrder.ASC)
            // searchAfter 
            .searchAfter(searchHits[searchHits.length - 1].getSortValues()));