es问题汇总--待完善

1. 查询某个索引库中数据总量

方式一:
CountRequest 鄙人喜欢这种方式

    public long getTotalNum(String indexName) throws IOException {
        CountRequest countRequest = new CountRequest(indexName);
        // 如果需要,你可以在这里添加查询条件
        // countRequest.query(QueryBuilders.matchQuery("field_name", "value"));
        CountResponse countResponse = esHighLevelClient.count(countRequest, RequestOptions.DEFAULT);
        return countResponse.getCount();
    }

方式二:
SearchRequest 这种方式只能查询出10000条。

        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices(index);
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.matchAllQuery());
        System.out.println("SDL语句:"sourceBuilder);
        searchRequest.source(sourceBuilder);
        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        long value = response.getHits().getTotalHits().value;
        System.out.println("数据总量:"+value);

优化方式,设置trackTotalHits(true)则可以获取数据总量

sourceBuilder.trackTotalHits(true);

2. 分页问题

分页类型:

  • 浅分页
  • 深度分页

浅分页 from+size

适用场景:适用于数据量不大、实时性要求高的场景。
示例代码

        SearchRequest searchRequest2 = new SearchRequest();
        searchRequest2.indices(index);
        SearchSourceBuilder sourceBuilder2 = new SearchSourceBuilder();

        for (int i = 1; i <= totalPage; i++) {
            
            //---------------from + size
            sourceBuilder2.from((i - 1) * 300);
            System.out.println("起始索引是:"+(i - 1) * 300);
            sourceBuilder2.size(300);
            
            searchRequest2.source(sourceBuilder2);
            SearchResponse searchResponse = restHighLevelClient.search(searchRequest2, RequestOptions.DEFAULT);
            SearchHits hits = searchResponse.getHits();
            SearchHit[] hits1 = hits.getHits();
            System.out.println("xxxx");
        }

        System.out.println("完成");

当起始索引+每页显示条数 from+size大于10000时,报错:
result window is too large, from + size must be less than or equal to
原因:
系统默认限制10000条。
系统为什么限制10000条?

es分页原理

------比如,现在要from为990,size为10,es会从每个分片中拿到前1000条数据,假如这个索引现在有4个分片,那么就会拿到4000条数据,然后在内存中对这4000条数据进行排序,然后从这4000条文档中取出前10条数据,4000条数据的存储,排序等操作都是在内存中完成,非常耗费资源。
------如果分页再继续深入下去,比如from为9990,size为10,那么就会从每个分片中先拿到前10000条数据,4个分片就是40000条数据,这时就要把4万条数据在内存中存储、排序等。如果分页再继续深入下去,也就是(from+size)*分片数量越大 ,越消耗资源,而且是倍数增长。
在这里插入图片描述

解决方案:

还是用from+size的方式进行分页,但是设置索引库index.max_result_window的值即可。

PUT yourindex/_settings
{
  "index.max_result_window": "1000000"
}

max_result_window 最大限制为 10亿
不推荐
参考:https://huaweicloud.csdn.net/637ee8fadf016f70ae4c9702.html
虽然这样设置在大数据量分页查询时能够解决result window is too large, from + size must be less than or equal to 这个问题,但是不推荐这样使用。
因为其会带来严重的后果,最常见的就是后期频繁的 OOM,而且很难发现原因。
看一下官方对该参数的解释:
在这里插入图片描述
ax_result_window本身是对JVM的一种保护机制,通过设定一个合理的阈值,避免初学者分页查询时由于单页数据过大而导致OOM。

在很多业务场景中经常需要查询10000条以后的数据,当遇到不能查询10000条以后的数据的问题之后,网上的很多答案会告诉你可以通过放开这个参数的限制,将其配置为100万,甚至1000万就行。

但是如果仅仅放开这个参数就行,那么这个参数限制的意义有何在呢?如果你不知道这个参数的意义,很可能导致的后果就是频繁的发生OOM而且很难找到原因

那么这个参数就完全不能动吗?当然不是,设置一个合理的参数阈值是需要通过你的各项指标参数来衡量确定的,比如你用户量、数据量、物理内存的大小、分片的数量等等。通过监控数据和分析各项指标从而确定一个最佳值,并非越大越好。

建议如果你不是对 ES 有足够的了解和使用经验,不要轻易修改max_result_window参数的阈值!

所以当数据量非常大时,分页就不要用form+size,推荐使用深度分页

深度分页 scroll

使用方式:

scroll 原理:

scroll 分页方式的原理与游标(cursor)类似。当你执行一个带有 scroll 参数的搜索查询时,Elasticsearch会为这次搜索创建一个快照(snapshot),并存储相关的搜索上下文(search context)。这个上下文包括查询本身、排序方式、聚合等所有与搜索相关的信息。

  • 首次POST /_search/scroll请求会返回一部分结果(基于size参数)以及一个scroll_id。
  • 使用这个scroll_id,你可以通过后续的POST /_search/scroll请求来获取更多的结果。
  • scroll参数定义了在多长时间内可以保持scroll上下文有效。如果在这个时间内没有新的scroll请求,那么scroll上下文就会被删除,无法再获取更多结果。
    使用RestHighLevelClient

适用场景:如日志导出、数据迁移等,当不适用于用户界面的分页。因为scroll获取的数据不是实时性的,而是保存快照那一刻的数据,也就意味着即使有新数据写入,也不会被包含在查询结果中。

// 初始化scroll搜索
POST /_search/scroll
{
    "size": 100,           // 每次返回的文档数量
    "scroll": "1m",        // 保持scroll上下文的活动时间,这里是1分钟
    "query": {
        "match_all": {}    // 可替换为任何需要的查询条件
    }
}

// 后续的scroll请求(在第一次请求返回后)
POST /_search/scroll
{
    "scroll": "1m",        // 保持与第一次请求相同的scroll上下文时间
    "scroll_id": "你的scroll_id" // 第一次请求返回的scroll_id
}
    public void TestScroll() throws IOException {
        SearchRequest searchRequest = new SearchRequest(index);

        //创建查询条件
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());
        // 设置每批获取的数量
        searchSourceBuilder.size(1000);

        searchRequest.source(searchSourceBuilder);
        // 设置滚动时间
        searchRequest.scroll(TimeValue.timeValueMinutes(5));

        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        String scrollId = searchResponse.getScrollId();


        do {
            for (SearchHit hit : searchResponse.getHits().getHits()) {
                //TODO 处理搜索结果
                System.out.println(hit.getSourceAsMap());
            }
            // 使用当前的滚动ID进行下一个批次的搜索
            SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId);
            scrollRequest.scroll(TimeValue.timeValueMinutes(5));
            scrollId = searchResponse.getScrollId();
            searchResponse = restHighLevelClient.scroll(scrollRequest, RequestOptions.DEFAULT);
        } while (searchResponse.getHits().getHits().length != 0);


        //清除Scroll请求状态
        ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
        clearScrollRequest.addScrollId(scrollId);
        restHighLevelClient.clearScroll(clearScrollRequest, RequestOptions.DEFAULT);

    }

深度分页 search_after

参考:https://blog.csdn.net/u011250186/article/details/125483759

原理

实现原理:

search_after 分页的方式是根据上一页的最后一条数据来确定下一页的位置,同时在分页请求的过程中,如果有索引数据的增删改查,这些变更也会实时的反映到游标上。

说明:

为了找到每一页最后一条数据,每个文档必须有一个全局唯一值,官方推荐使用 _uid 作为全局唯一值,其实使用业务层的 id 也可以。
说明:使用search_after查询需要将from设置为0或-1,当然也可以不写。
需要注意的是:

1)sort字段的选择

如果search_after中的关键字为***,那么***123的文档也会被搜索到,所以在选择search_after的排序字段时需要谨慎,可以使用比如文档的id或者时间戳等。另外,search_after并不是随机的查询某一页数据,而是并行的滚屏查询;search_after的查询顺序会在更新和删除时发生变化,也就是说支持实时的数据查询。

2)无法跳页请求

因为每一页的数据依赖于上一页最后一条数据,所以无法跳页请求。

   public void TestSearchAfter() throws Exception {
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices(index);

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.from(0).size(1000);
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());

        // 指定排序,并设置sort values为上一次查询的最后一条记录的sort values
        searchSourceBuilder.sort("_id", SortOrder.ASC);

        List<Map<String, Object>> mapList = new ArrayList<>();

        this.search(searchRequest,searchSourceBuilder,mapList, null);

        System.out.println(mapList.size());
    }

    private void search(SearchRequest searchRequest,
                            SearchSourceBuilder searchSourceBuilder,
                            List<Map<String, Object>> totalList, Object[] objects) throws Exception{
        if(Objects.nonNull(objects)){
            searchSourceBuilder.searchAfter(objects);
        }
        searchRequest.source(searchSourceBuilder);
        System.out.println(searchSourceBuilder);
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        SearchHit[] hits = searchResponse.getHits().getHits();
        
        if(Objects.nonNull(hits) && hits.length > 0){
            List<Map<String, Object>> collect = Arrays.stream(hits).map(SearchHit::getSourceAsMap).collect(Collectors.toList());
            
            //TODO 处理数据 ,可以不要 totalList参数 
            totalList.addAll(collect);
            
            search(searchRequest,searchSourceBuilder,totalList,hits[hits.length - 1].getSortValues());
        }

    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/637695.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

内脏油脂是什么?如何减掉?

真想减的人&#xff0c;减胖是很容易的&#xff0c;但想要形体美又健康&#xff0c;还是得从减内脏油脂开始&#xff0c;那么&#xff0c;问题来了&#xff0c;什么是内脏油脂&#xff1f; 油脂它分部于身体的各个角落&#xff0c;四肢、腹部、腰、臀部、脸、脖子...等&#xf…

暴雨信息液冷计算解决方案亮相CCIG 2024

5月24日&#xff0c;2024中国图象图形大会&#xff08;CCIG&#xff09;在陕西西安正式开幕。作为涵盖图像图形各专业领域的综合性的全国性学术会议&#xff0c;CCIG面向开放创新、交叉融合的发展趋势&#xff0c;为图像图形相关领域的专家学者和产业界的同仁&#xff0c;搭建了…

深入用户内心:设计师如何通过可用性测试洞察用户需求

可用性测试是指让用户体验产品的原型或成品。设计师通过观察和分析用户的使用行为和感受&#xff0c;进一步合理地改进产品的设计方法。你可能会想知道我们可以用什么方法来测试可用性&#xff1f;随着互联网行业的快速迭代更新&#xff0c;可用性测试衍生出了许多类型和方法。…

【C++初阶】—— 类和对象 (下)

&#x1f4dd;个人主页&#x1f339;&#xff1a;EterNity_TiMe_ ⏩收录专栏⏪&#xff1a;C “ 登神长阶 ” &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 类和对象 1. 运算符重载运算符重载赋值运算符重载前置和后置重载 2. 成员函数的补充3. 初始化列…

报错:找不到或无法加载主类 com.example.SpringbootApplication(idea)

OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended 错误: 找不到或无法加载主类 com.example.SpringbootApplication 原因: java.lang.NoClassDefFoundError: com/example/SpringBootAppli…

C++---运算符重载

运算符重载介绍 在类中重新定义运算符&#xff0c;赋予运算符新的功能以适应类的运算&#xff0c;就称为运算符重载。 运算符重载是一种形式的C多态,它使得对象操作更直观,本质上也是属于函数重载。 实际上&#xff0c;我们已经在不知不觉之中使用了运算符重载。例如&#xff…

【JAVA |再谈接口、Object、内部类】Object类中子类重写,Cloneable 接口、比较器、内部类

✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天开心哦&#xff01;✨✨ &#x1f388;&#x1f388;作者主页&#xff1a; &#x1f388;丠丠64-CSDN博客&#x1f388; ✨✨ 帅哥美女们&#xff0c;我们共同加油&#xff01;一起…

python写页面自动截图

from selenium import webdriver def take_screenshot(url, file_path):driver webdriver.Chrome()driver.get(url)driver.save_screenshot(file_path)driver.quit() if __name__ __main__:take_screenshot(http://baidu.com, D:\桌面\wang.png)要安装selenium还要安装google…

React类组件生命周期详解

在React的类组件中&#xff0c;从组件创建到组件被挂载到页面中&#xff0c;这个过程react存在一系列的生命周期函数&#xff0c;最主要的生命周期函数是componentDidMount、componentDidUpdate、componentWillUnmount 生命周期图例如下 1. componentDidMount组件挂载 如果你…

网络安全资源和参考指南

由美国国防部&#xff08;DoD&#xff09;发布的《网络安全资源和参考指南》&#xff0c;旨在为美国政府、商业部门以及美国盟友和伙伴之间的安全合作提供有用的、现成的参考资料。文档涵盖了网络安全规范、最佳实践、政策和标准&#xff0c;这些都是由美国联邦政府、国防部以及…

KubeSphere 社区双周报|2024.05.09-05.23

KubeSphere 社区双周报主要整理展示新增的贡献者名单和证书、新增的讲师证书以及两周内提交过 commit 的贡献者&#xff0c;并对近期重要的 PR 进行解析&#xff0c;同时还包含了线上/线下活动和布道推广等一系列社区动态。 本次双周报涵盖时间为&#xff1a;2024.05.09-05.23…

CCF20230301——田地丈量

CCF20230301——田地丈量 代码如下&#xff1a; #include<bits/stdc.h> using namespace std; int main() {int n,a,b;cin>>n>>a>>b;int x1,x2,y1,y2,x,y,sum0;for(int i0;i<n;i){cin>>x1>>y1>>x2>>y2;xmin(x2,a)-max(x1,…

【科普知识】伺服电机中的内置制动器

在工业自动化和机器人技术快速发展的今天&#xff0c;伺服电机作为核心驱动元件&#xff0c;其性能与功能直接影响整个系统的运行效率与稳定性。 近年来&#xff0c;一体化伺服电机技术不断融合创新&#xff0c;并逐步加入了许多新的硬件和软件的功能&#xff0c;为工业自动化领…

SpringBoot+Vue开发记录(五)-- 数据库设计

我去&#xff0c;时隔这么久又开始了QAQ。主要是还是自己太懒了。 本篇文章的主要内容是数据库设计。 先简单创建个数据库&#xff1a; 这是创建好了的&#xff1a; 一、数据库设计 先就做一个很简单的设计&#xff0c;里面就只有用户和题。 大概就这样&#xff1a; 二、创…

GQL 来了!ISO/IEC 正式发布 GQL 数据库国际标准!

历时四年筹备&#xff0c;超过20个国家的标准和技术专家参与制定&#xff0c;ISO/IEC GQL &#xff08;图查询语言&#xff09;标准于2024年4月12日正式发布&#xff01; 作为国际标准化组织&#xff08;ISO&#xff09;继 1987年 发布SQL后&#xff0c;唯一发布的数据库查询语…

express路由的介绍与使用

一、什么是路由&#xff1f; 官方&#xff1a;路由确定了应用程序如何响应客户端对特定端点的请求 通俗来说&#xff1a;在Web开发中&#xff0c;路由是指根据不同的请求路径和请求方法&#xff0c;将请求分发到相应的处理函数、模块或中间件。简单来说&#xff0c;就是URL到…

【运维心得】双WAN配置的一个误区

目录 双WAN配置及优势 实际案例 解决之道 最后总结 双WAN配置及优势 什么是双WAN配置&#xff0c;这里就不多赘述&#xff0c;简单的说&#xff0c;首先你要有一台支持双WAN口的路由器&#xff0c;目前大多数企业级路由器都具备了这个功能。甚至有些家用路由器也有此类功能…

揭秘:水滴式粉碎机为何如此受欢迎

在粉碎机市场中&#xff0c;水滴式粉碎机以其D特的设计和G效的性能脱颖而出&#xff0c;成为众多用户的选择产品。那么&#xff0c;水滴式粉碎机究竟有何魅力&#xff0c;能够赢得如此广泛的赞誉呢&#xff1f; 首先&#xff0c;水滴式粉碎机的G效性能是其受欢迎的关键因素之一…

【软件设计师】下午题总结-数据流图、数据库、统一建模语言

下午题总结 1 试题一1.1 结构化语言 2 试题二弱实体增加权限增加实体间联系和联系的类型 3 试题三3.1 UML关系例子 3.2 例子&#xff08;2016上半年&#xff09;3.3 设计类分类3.3.1 接口类3.3.2 控制类3.3.3 实体类 3.4 简答题3.4.1 简要说明选择候选类的原则3.4.2 某个类必须…

基于EBAZ4205矿板的图像处理:09基于sobel边缘检测的图像锐化

基于EBAZ4205矿板的图像处理&#xff1a;09基于sobel边缘检测的图像锐化 项目全部文件 随后会上传项目全部文件 先看效果 锐化的有点过头了&#xff0c;不过我也懒得改了&#xff0c;想要改也很简单&#xff0c;无非就是给卷积运算后的结果加个系数&#xff0c;通过改系数调…