精华内容
下载资源
问答
  • 2021-09-24 14:55:15

            Elasticsearch对数据的检索非常的快,但是Elasticsearch使用分页时,它也会随之查询位置越深而变得很慢。Elasticsearch默认使用from + size的分页方式。如果size + from > 10000时,Elasticsearch还会出现如下错误:

    org.elasticsearch.search.query.QueryPhaseExecutionException: Result window is too large, from + size must be less than or equal to: [10000] 

            出现如上错误的原因是:默认查询长度为10000,它可以通过如下方式修改:

    http://ip:port/index/_settings?preserve_existing=true 
    
    {
      "max_result_window": "2000000000"
    }

           其实,Elasticsearch提供scroll查询,它有效地执行大批量的文档查询,而又不用付出深度分页那种代价。scroll查询允许先做查询初始化,然后再批量地拉取结果。它有点像传统数据库中的 cursor。

            scroll查询的使用也非常简单,这里重要有一个scroll查询过期时间的概念。scroll查询窗口需要消耗资源,设置过期时间可以减少资源的消耗,最大可以设置过期时间为24小时。也可以手动销毁。每次做scroll查询的时候也会刷新过期时间。

            首次查询使用方法,它返回结果包括一个字段 _scroll_id,通过_scroll_id到 _search/scroll 查询接口获取下一批结果:

    GET http://ip:port/index/type/_search?scroll=1m 
    {
        "query": { "match_all": {}},
        "sort" : ["_doc"], 
        "size":  1000
    }

            通过 _scroll_id 查询:

    GET http://ip:port/index/type/_search/scroll
    {
        "scroll": "1m", 
        "scroll_id" : "xxxxxxx"
    }

            手动删除scroll查询:

    DELETE http://ip:port/index/type/_search/scroll
    {
        "scroll_id" : "xxxxxxx"
    }

    更多相关内容
  • 问题:某日下午正开心的逛着超市,突然收到线上es机器的fgc电话告警,随之...通过监控页发现入口流量并没有明显抖动,考虑到集群中的不同索引以及不同查询类型,总的入口流量可能会掩盖一些问题,所以继续查看各索引...

    问题:

    某日下午正开心的逛着超市,突然收到线上es机器的fgc电话告警,随之而来的是一波es reject execution,该es机器所处集群出现流量抖动。

    排查:

    回到家打开监控页面,内存占用率有明显的上升,通常服务端不会无端的爆内存,首先排查可能性最高的:读写流量变化。

    通过监控页发现入口流量并没有明显抖动,考虑到集群中的不同索引以及不同查询类型,总的入口流量可能会掩盖一些问题,所以继续查看各索引的分操作流量监控,发现索引 A 的scroll流量在故障发生时存在明显的波动,从正常的 10qps 以内涨到最高 100qps 左右,这对于普通查询来说并不高,看来是 scroll 查询有些异样。

    起因1:

    先说结论:scroll 查询相对普通查询占用的内存开销大很多,考虑到遍历数据的场景,安全的量是控制在 10qps 左右。

    相比于普通query,scroll 查询需要后端保留遍历请求的上下文,具体的就是当有init scroll请求到达时,当时的 index searcher 会持有全部索引段的句柄直至scroll请求结束,如果处理不当,比如段缓存等,容易在server端占用大量内存;另外, scroll 查询还需要在server端保存请求上下文,比如翻页深度、scroll context等,也会占用内存资源。

    在后续的测试中,客户端单线程使用scroll查询遍历百万级别的索引数据,server端的CPU占用率高达70%左右,观察进程的CPU占用,发现大部分的CPU时间都耗在gc上,这使得server没有足够的CPU时间调度其他任务,导致正常的读写请求不能被及时响应。

    # 压测机器配置:1c2g x 10

    # 索引配置:5 number_of_shards x 1 number_of_replica,共计约180万数据

    起因2:

    继续排查scroll执行的查询内容,发现的主要有两种类型。

    其一:

    {

    "query": {"bool":{"must":[{"terms":[11,22,…2003]}]}},

    "size":200

    }

    # terms子句中包含200个id

    上面的示例query省略了其他一些过滤条件,白话一下这个查询的含义:

    从索引中查询id字段值为数组所包含的200条记录

    可以看到的几个特征是:

    没有filter子句,terms条件在must子句

    这个查询最多返回200条记录,一次查询就可以得到全部数据

    其二:

    {

    "query": {"bool":{"must":[

    {"range":{"create_time":{"gt":0, "lte":604800}}},

    {"term":{"shop_id":1}}

    ]}},

    "size":200

    }

    # range条件包含的数据大约为1000条

    # 全索引包含的数据大约1000万条

    # create_time不固定,但是区间固定在1周

    这里也省略了一些其他干扰条件,只保留最重要的,白话过来的含义:

    从1000万全量索引中查询shop_id=1并且create_time在符合条件区间内的数据,

    条件区间每10秒变更一次,也就是每10秒查询一次当前时刻之前1周的新数据.

    可以得出的几个结论:

    size为200,要访问全部数据至少需要5次查询

    create_time的变更很小,类似于 (0, 603800] => (5, 604805],所以每次查询该子条件命中的记录数变化也都不大,都有几百万条

    没有filter子句

    并没有发现filter或者must_not这样在官方文档中明确标明的filter context条件,但是实际上的filter cache在scroll发生期间单机从 500 MB 左右逐渐升高到 6 GB(配置的filter cache最大空间),理论上说不通,直接从代码里找答案。

    跟踪query流程,发现bool子句中不论是must还是filter,最终被rewrite之后没有本质上的区别,判断是否可以进入filter cache的条件是:

    段内最大文档数是否在阈值范围内(Es的filter缓存以段为单位)

    查询出现频次是否超过阈值

    而在出现频次这个部分,Lucene缓存策略还会有isCostly这样的判断,目的是尽量将高消耗的查询尽可能早的缓存起来,提高查询性能,符合isCostly判断的查询包括 terms 和 range 等查询,只要重复出现2次即会被缓存起来,结合起来分析:

    terms查询并不需要scroll查询,使用普通查询就能解决需求,使用scroll查询增加了server负载

    range查询重复次数达到了isCostly阈值,也就是说每次遍历数据都会往filter cache中丢入几百万的缓存value,而且命中率极低(下次scroll查询的range起止条件有细微的变化),加大了server的gc负担

    解决:

    通过上面的分析,我们可以看到有两个因素的影响导致了server的拒绝响应:

    大量的scroll并发

    不当的range请求,具体又可以拆分为:高频次,每10秒一次

    变化快,每次查询的起止范围都有10秒的后延

    命中数大,百万级别的命中数

    针对上面的几点各个击破就是我们的解决方案:

    scroll请求:

    纠正不当使用的terms+scroll查询,使用普通查询;

    推荐使用search_after替换scroll请求,虽然在效率上有所降低,但是有两个优势:

    可以重试,scroll如果重试可能会丢失部分数据

    资源占用低,在相同的测试环境下,CPU占用率只有10%左右

    不当的range请求:

    高频次:降低请求频率,限制到至少1分钟一次,当然不是根本解决方案,推荐将类似的遍历数据请求改到db或者hbase等介质

    变化快:粗暴点的解决方案是限制时间单位到小时级别,优雅点的话:

    将时间条件拆分为粗粒度和细粒度的组合,粗粒度以若干小时为单位,细粒度支撑到分钟或者秒级

    细粒度条件使用script方式执行,原理是filter cache的frequency是用LinkedHashMap作为key容器的,用来累积查询次数,而key的hash计算,普通query是根据查询的条件和值来作为hash输入的,而script查询是使用当前实例的引用,这样就能避免查询被累积(因为每次的hashcode都不一样)

    命中数大:通过粗细粒度划分可以降低成本

    额外补充:这里是根据Es5.1.2版本得到的结论,

    最新版本中script查询的hash计算方式也改为根据脚本的内容和参数来进行了

    全文完。

    展开全文
  • java使用ElasticSearch的scroll查询,高效的解决es查询数量的限制。 一、为什么要使用ES的scroll (1)首先我们要明白es的查询机制:ES的搜索是分2个阶段进行的,即Query阶段和Fetch阶段。 Query阶段比较轻量级,...

    java使用ElasticSearch的scroll查询,高效的解决es查询数量的限制。

    一、为什么要使用ES的scroll

    (1)首先我们要明白es的查询机制:ES的搜索是分2个阶段进行的,即Query阶段和Fetch阶段

    • Query阶段比较轻量级,通过查询倒排索引,获取满足查询结果的文档ID列表。

    • Fetch阶段比较重,需要将每个分片的查询结果取回,在协调结点进行全局排序。 通过From+size这种方式分批获取数据的时候,随着from加大,需要全局排序并丢弃的结果数量随之上升,性能越来越差。

    (2)es在进行普通的查询时,默认只给查询出来十条数据。

    ​ 通过设置size的值可以使查询结果从10增大到1000条数据,当超出1000条数据的时候就会只显示出来1000条数据。

    ​ 为了解决上面的问题可以采用一种效率比较低的方法,在创建索引的时候添加如下配置

    • 
      "settings":{
      		"index":{
      			"max_result_window": 在这里填入你需要的大小				}
      			}
      

    (3)如果进行高效的查询呢?那就需要使scroll滚动查询了。

    Scroll查询,先做轻量级的Query阶段以后,免去了繁重的全局排序过程。 它只是将查询结果集,也就是doc_id列表保留在一个上下文里, 之后每次分批取回的时候,只需根据设置的size,在每个分片内部按照一定顺序(默认doc_id续), 取回size数量大小的数据即可。

    二、如何使用scroll

    (1)首先引入elasticsearch的坐标

    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
    		</dependency>
    

    (2)编写如下代码

    
        /**
         * 使用es的scroll方法来滚动查询es的数据,可以有效的解决大数据容量读取的限制
         * @param index  es的索引名称
         * @param host   es的主机ip号
         * @param port   es的端口号
         * @param beginDate   构造查询条件需要的条件之一 (可以根据自己需求定义es的查询条件)
         * @param endDate     构造查询条件需要的条件之一 (可以根据自己需求定义es的查询条件)
         */
        public void scrollDemo(String index,String host,int port,String beginDate,String  endDate) throws ParseException {
            RestHighLevelClient restHighLevelClient=new RestHighLevelClient(RestClient.builder(new HttpHost(host,port,"http")));
            //构造查询条件
            SearchRequest searchRequest = new SearchRequest(index);
            SearchSourceBuilder builder = new SearchSourceBuilder();
            //设置查询超时时间
            Scroll scroll = new Scroll(TimeValue.timeValueMinutes(5L));
            builder.query(QueryBuilders.rangeQuery("datetime").gte(beginDate).lte(endDate));
            //设置最多一次能够取出1000笔数据,从第1001笔数据开始,将开启滚动查询  
            //PS:滚动查询也属于这一次查询,只不过因为一次查不完,分多次查
            builder.size(1000);
            searchRequest.source(builder);
            //将滚动放入
            searchRequest.scroll(scroll);
            SearchResponse searchResponse = null;
            try {
                searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
            } catch (IOException e) {
                System.out.println("查询索引库失败");
            }
            SearchHits hits= searchResponse.getHits();
            SearchHit[] hit= hits.getHits();
            /**
            *在这个位置已经读到了前一千条数据,可以在这先对这一千数据进行处理。下面滚动查询剩下的数据
            */
            //记录要滚动的ID
            String scrollId = searchResponse.getScrollId();
            //滚动查询部分,将从第1001笔数据开始取
            SearchHit[] hitsScroll = hits.getHits();
            while (hitsScroll != null && hitsScroll.length > 0 ) {
                //构造滚动查询条件
                SearchScrollRequest searchScrollRequest = new SearchScrollRequest(scrollId);
                searchScrollRequest.scroll(scroll);
                try {
                    //响应必须是上面的响应对象,需要对上一层进行覆盖
                    searchResponse = restHighLevelClient.scroll(searchScrollRequest, RequestOptions.DEFAULT);
                } catch (IOException e) {
                    System.out.println("滚动查询失败");
                }
                scrollId = searchResponse.getScrollId();
                hits = searchResponse.getHits();
                hitsScroll = hits.getHits();
                /**
                *在这个位置可以对滚动查询到的从1001条数据开始的数据进行处理。
                */
            }
            //清除滚动,否则影响下次查询
            ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
            clearScrollRequest.addScrollId(scrollId);
            ClearScrollResponse clearScrollResponse = null;
            try {
                clearScrollResponse = restHighLevelClient.clearScroll(clearScrollRequest,RequestOptions.DEFAULT);
            } catch (IOException e) {
                System.out.println("滚动查询删除失败");
            }
            //清除滚动是否成功
            boolean succeeded = clearScrollResponse.isSucceeded();
        }
    
    
    展开全文
  • es scroll查询采坑实录

    2021-11-03 16:01:34
    es scroll查询采坑实录问题描述问题排查过程解决方案人生就是不断采坑的过程啊 问题描述 es 采用scroll方式查询数据时出现大量数据丢失。用from查询hint的总数6774,scroll查询hint的总数2558,数据差别明显 。 问题...

    问题描述

    es 采用scroll方式查询数据时出现大量数据丢失。用from查询hint的总数6774,scroll查询hint的总数2558,数据差别明显 。

    问题排查过程

    1. 进容器分别执行from和scroll命令查询,发现scroll执行时es抛出异常,
      Trying to create too many scroll contexts. Must be less than or equal to: [500]. This limit can be set by changing the [search.max_open_scroll_context] setting.
      如下图;
      在这里插入图片描述

    2. 针对提示信息,修改参数 search.max_open_scroll_context 扩大至10000,问题依旧存在;

    3. 怀疑代码未clear scrollId,检查代码,未发现问题;

    4. 百度之,结果千篇一律,未果;

    5. google之,果然发现问题,es7.7之前版本存在bug,scroll context 计数器存在问题。百度误我;
      在这里插入图片描述

    解决方案

    1.search.max_open_scroll_context 设置Integer最大值
    2.重启es
    3.升级es版本至7.7.x或之后版本

    人生就是不断采坑的过程啊

    Alt

    展开全文
  • 在ElasticSearch中实现分页查询的方式有两种,...因为这个scroll相当于维护了一份当前索引段的快照信息,这个快照信息是你执行这个scroll查询时的快照。在这个查询后的任何新索引进来的数据,都不会在这个快照中查询
  • 一般而言,es返回数据的上限是10000条,如果超过这个数量,就必须使用scroll查询。所谓scroll查询就类似DBMS中的游标,或者快照吧,利用查询条件,在第一次查询时,在所有的结果上形成了一个快照,然后再分批分次的...
  • Jest scroll查询

    2019-11-27 13:05:58
    @Test public void testSerialScroll() throws IOException { BoolQueryBuilder builder = QueryBuilders.boolQuery();... SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().size(SCROLL...
  • ElasticSearch scroll查询原理

    千次阅读 2020-09-27 11:11:24
    一、 ES搜索两阶段简介 ES的搜索是分2个阶段进行的,即Query阶段和Fetch阶段。...二、 scroll分析Scroll查询,先做轻量级的Query阶段以后,免去了繁重的全局排序过程。 它只是将查询结果集,也...
  • elasticsearch scroll查询

    千次阅读 2020-01-08 18:03:56
    elasticsearchscroll查询 一般的分页查询请求:from、size、n(主分片数), 请求会分发到对应主分片或者副本分片上,分片向协调节点返回(from+size)条数据,n...scroll查询:如果要查询100页数据,每页数据100...
  • elasticsearch scroll查询原理

    千次阅读 2020-07-20 18:21:36
    ES的搜索是分2个阶段进行的,即Query阶段和Fetch阶段。...而Scroll查询,先做轻量级的Query阶段以后,免去了繁重的全局排序过程。 它只是将查询结果集,也就是doc id列表保留在一个上下文里,之后每次分...
  • 游标查询scroll查询,可以用于对 Elasticsearch 有效地执行大批量的文档查询,而又不用付出深度分页那种代价。scroll查询可以分为以下两个步骤。启动游标查询GET /host/_search?scroll=1m其中的scroll=1m表示游标...
  • Elsaticsearch-Scroll查询详解

    千次阅读 2020-09-23 15:26:26
    scroll查询 可以用来对 Elasticsearch 有效地执行大批量的文档查询,而又不用付出深度分页那种代价。 游标查询允许我们 先做查询初始化,然后再批量地拉取结果。 这有点儿像传统数据库中的cursor。 游标查询会取...
  • 如果涉及大量数据查询的话,一次性取回所有数据显得非常不可靠,一方面 ES 可能会被长时间占用,另一方面在网络连接方面也要一直保持连接状态。 以查询电商商品为例,如果当用户查看商品时候,将所有数据都返回,这...
  • scroll 查询 可以用来对 Elasticsearch 有效地执行大批量的文档查询,而又不用付出深度分页那种代价。 游标查询允许我们 先做查询初始化,然后再批量地拉取结果。 这有点儿像传统数据库中的 cursor 。 游标查询会取...
  • try: es_scroll_size = 1000 with Elasticsearch( [self.hosts], # 连接集群,以列表的形式存放各节点的IP地址 sniff_on_start=True, # 连接前测试 sniff_on_connection_fail...
  • 我们在 Elasticsearch API的基础上实现了一个日志查询系统,支持最基本的时间范围选择以及关键词搜索高亮,并且日志展示的表格支持异步分页。 有天用户反馈,查询的时候页面报错 Result window is too large, from +...
  • ElasticSerach RestHighLevelClient 查询,高亮分页查询scroll分页 查询scroll 高亮查询
  • Elasticsearch Scroll和Slice Scroll查询API使用案例 the best elasticsearch highlevel java rest api-----[url=https://my.oschina.net/bboss/blog/1942562]bboss[/url] [b]本文内容[/b] [list] [*]...
  • Elasticsearch有两种分页方式,一种是通过from和size条件来实现,但是该方法开销比较大,另一种是利用scroll来实现,通过scroll来实现分页获取所有的数据,下面是利用python实现的scroll获取全部数据的方式: ...
  • 一、前言:ES 普通的分页查询有深分页限制,默认是10000条。...scroll相当于维护了一份当前索引段的快照信息,这个快照信息是你执行这个scroll查询时的快照。在这个查询后的任何新索引进来的数据,...
  • 如上是查询title、genre中带有old或者包含old的文档,并进行相关性打分,将打分结果*字段year的值,然后进行排序。 { "took" : 2, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, ...
  • ElasticSearch Scroll滚动查询查询数据超过10000) ElasticSearch官方默认查询数据是10000条,查询第10001时会报错:Result window is too large, from + size must be less than or equal to... 以下是From/...
  • ES使用scroll游标查询

    2021-10-26 17:50:04
    由于ES单次查询数据上限1W条,正常查询1W条后程序会异常,ES提供了scroll-api来解决 例子:基于scroll实现月度销售数据批量下载 2条数据,做一个演示,每个批次下载一条宝马的销售记录,分2个批次给它下载完 ...
  • 写在前面 因为工作上的需要,记录下spring-data-elasticsearch与spring的配置,以及对应的...在Kibana中,使用的查询的DSL如下 GET /{index_name}/_search { "from":10, "size":20, "...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 44,619
精华内容 17,847
关键字:

scroll查询