ElasticSearch中的Scroll机制

Posted 编程笔记

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ElasticSearch中的Scroll机制相关的知识,希望对你有一定的参考价值。

Elasticsearch 中的 Scroll Id 机制是一种用于批量检索大量数据的机制。

当我们需要批量获取大量数据时,直接使用搜索 API 可能会遇到一些性能问题。此时, Scroll Id 机制则能够帮助我们优化查询性能。该机制类似于一个游标,可以通过 Scroll API 来获取每个批次的结果。每个结果都包含一个新的 Scroll Id,该 ID 可以用于检索下一个批次的结果,这样我们就可以按需逐批获取数据。

使用 Scroll Id 机制的好处在于可以取代传统的分页方式,因为它不需要在每次搜索的结果中指定大小和偏移量。

此外,由于 Elasticsearch 并不需要在每次搜索中重建内部状态,所以 Scroll Id 机制可以更高效地处理批量数据。

虽然 Elasticsearch 中的 Scroll Id 机制具有很多优点,但也存在一些缺点。

具体来说, Scroll Id 机制可能会导致以下问题:

1. Scroll Id 机制需要占用服务器内存以保存游标状态,如果数据量过大或者游标过多,可能会导致 Elasticsearch 的内存占用过高,从而影响其他服务的正常运行。

2. 使用 Scroll Id 机制获取结果时,必须在每一个批次结果返回后立即对结果进行处理。如果处理速度跟不上结果获取速度,可能会导致数据积压,导致内存不够用或磁盘 I/O 不足等问题。

3. Scroll Id 机制只能在游标有效期内获取数据,一旦过期则无法获取。默认的有效期为 1 分钟,但可以通过设置 Search Request 上的 scroll 参数来更改有效期。如果游标过期但未及时处理数据,可能会导致数据丢失。

4. Scroll Id 机制只是针对检索,无法保证数据不被修改或删除。如果数据在检索过程中被修改或删除,可能会导致 Scroll Id 所指向的数据不准确。

 

综上所述,Scroll Id 机制是一种不错的批量检索机制,但需要注意消耗内存、处理速度、有效期和数据修改等问题。

ElasticSearch操作之游标查询Scroll Search

一.  什么是游标查询(Scroll)

  顾名思义,相当于用一把游标标记查询的位置.

 

二.  为什么要使用游标查询

  在默认情况下,ES查询每次返回的数量最多只有1W条,且只能是前1W条.

  这意味着,在不修改配置的情况下,想通过分页的方式(如下)拿到1W条之后的数据是做不到的

GET /索引/类型/_search
{
  "size": 10000, 
  "from": 5000, 
  "query": {
    ...   
  }, 
  "aggs": {
    ...  
  }
}

所以自然就有了游标查询.

 

三.  如何使用游标查询

DSL的用法:

GET 索引/类型/_search?scroll=1m
{
  "size": 10000,
  "query": {
    "match_all": {}
  }
}

1m表示:过期时间1分钟

 

查询结果的第一行会有:

  "_scroll_id": "DnF1ZXJ5VGhlbkZldGNoBAAAAAAABO-dFmRFSU9NM1VNU2JxNG9UUlNnSmpXMVEAAAAAAL7J_hYxT0dJOVJVMVFxU2I0N2xCR2IyVzJnAAAAAAC-    SmQWWk1aN0sxUmRSQmFNS3EwVFh0R0luUQAAAAAAvkplFlpNWjdLMVJkUkJhTUtxMFRYdEdJblE=",

这个_scroll_id就相当于书签,之后的查询带着这个书签,就能根据size不断拿到之后的数据,但是前提是在过期时间之内

 

之后的查询DSL:

GET _search/scroll
{
  "scroll":"1m",
  "scroll_id":"DnF1ZXJ5VGhlbkZldGNoBAAAAAAABPP1FmRFSU9NM1VNU2JxNG9UUlNnSmpXMVEAAAAAAL7OTxYxT0dJOVJVMVFxU2I0N2xCR2IyVzJnAAAAAAC-j70WVVlOZkxQRzJRLXlMRlVMbEQtalBfUQAAAAAAyWm-Fk9HdGx1b3VsUXRLZHV4c1E1OExja0E="
}

将获取的scroll_id作为条件继续查询即可,这里不需要再指定索引和类型,因为scroll_id的唯一性.

在过期时间内,之后的查询的scroll_id是不变的.

 

四.  基于java代码:

     RestClient lowClient = RestClient.builder(new HttpHost("主机",端口))
                .setMaxRetryTimeoutMillis(300000).build();
        RestHighLevelClient client = new RestHighLevelClient(lowClient);
        SearchRequest request = new SearchRequest("索引").types("类型");
     //这里一次查1W条 SearchSourceBuilder sourceBuilder
= new SearchSourceBuilder().size(10000); request.source(builder).searchType(SearchType.DEFAULT); //这句代码就是设置游标查询和过期时间
     request.scroll(TimeValue.timeValueMinutes(
5)); SearchResponse response = client.search(request);      // search     SearchResponse response = client.search(request);     //定义游标
    String scrollId
= null;     if (response != null && response.getHits().getHits().length > 0) {    for (SearchHit hit : response.getHits().getHits()) {   //TODO    }
     //拿到游标    scrollId
= response.getScrollId();     }     //一直查询,直到没有游标返回(查询到底了)     while (true){    if(scrollId == null){   break;    }   SearchScrollRequest searchScrollRequest = new SearchScrollRequest(scrollId).scroll(TimeValue.timeValueMinutes(5));;   response = client.searchScroll(searchScrollRequest);   if (response != null && response.getHits().getHits().length > 0) {   for (SearchHit hit : response.getHits().getHits()) { //TODO   }   scrollId = response.getScrollId();   }else {   break;   }     }

到这里,游标查询的基本操作就OK了.有一点需要注意:

  游标的方式,相当于mysql中生成快照的方式,所以如果在游标查询期间有增删改操作,是获取不到最新的数据的.

以上是关于ElasticSearch中的Scroll机制的主要内容,如果未能解决你的问题,请参考以下文章

Elasticsearch利用scroll查询获取所有数据

Elasticsearch - Scroll

ElasticSearch Scroll 游标搜索

ElasticSearch如何一次查询出全部数据——基于Scroll

Elasticsearch分页查询

Elasticsearch的性能优化