ES分页查询的最佳实践:三种方案

Elasticsearch(ES)中进行分页查询时,最佳实践取决于具体的使用场景和需求。

以下是对每种分页方法的简要分析以及它们适用的情况:

1. From + Size

  • 最常见且直观的方法,通过from参数指定跳过多少条记录,size参数指定每次返回多少条记录。
  • 优点:实现简单,适用于小规模或浅层分页,即前几页查询。
  • 缺点 :随着from值增大,查询效率会显著降低,尤其是在深度分页的情况下(例如,查询很多页之后的数据),因为ES需要遍历所有之前的结果才能找到指定偏移的结果集,这对分布式系统来说成本非常高。

2. Scroll API

  • 提供了一种持续检索大量数据的方式,创建一个"滚动"上下文,可以在一段时间内保持一致性视图。
  • 优点:非常适合大数据量的批量读取或深度分页,尤其是在不需要考虑数据实时更新的情况下,如数据导出或批处理任务。
  • 缺点:滚动上下文会占用服务器资源,且对实时性要求高的场景不合适,因为它反映的是某个时间点的快照状态,不能反映出滚动上下文创建后数据的变化。
  • 从ES 5.0版本开始提供,用于克服from+size在深度分页时的性能瓶颈。
  • 优点 :利用 _score 或用户定义的排序字段来进行连续查询,避免了大规模跳跃式分页的问题。相比from+size,它在深度分页时性能更优,同时能够更好地处理实时变化的数据。
  • 缺点 :需要有稳定的排序字段,并且不是所有场景下都能方便地转换为search_after模式。

代码示例

java 复制代码
package org.example;

import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchScrollRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.MatchAllQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

public class ESScrollMain {
    private static final String indexName = "kibana_sample_data_logs";

    public static void main(String[] args) throws IOException {
        System.out.println("Hello and welcome!");
        RestClientBuilder builder = RestClient.builder(new HttpHost("10.x.x.x", 9200, "http"));
        RestHighLevelClient client = new RestHighLevelClient(builder);

        SearchRequest searchRequest = new SearchRequest(indexName);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        // hit 返回值(bool 查询返回条数)
//        searchSourceBuilder.size(0);
//        searchSourceBuilder.from(0);
        searchSourceBuilder.trackTotalHits(true);
        // 超时时间60s
        MatchAllQueryBuilder search = QueryBuilders.matchAllQuery();
        searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        searchSourceBuilder.size(2000);
        searchSourceBuilder.query(search);

        long scrollTime = 30L;
        searchRequest.source(searchSourceBuilder);
        searchRequest.scroll(TimeValue.timeValueSeconds(scrollTime));

        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

        String scrollId = searchResponse.getScrollId();
        SearchHit[] hits = searchResponse.getHits().getHits();

        int count = 0;
        int batch = 1;
        System.out.println("初始结果条数:" + count);
        count += hits.length;
        System.out.println("滚动第" + batch + "批结果总条数:" + count);
        while (hits != null && hits.length > 0) {
            batch++;
            SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId);
            scrollRequest.scroll(TimeValue.timeValueSeconds(scrollTime));
            searchResponse = client.scroll(scrollRequest, RequestOptions.DEFAULT);
            scrollId = searchResponse.getScrollId();
            hits = searchResponse.getHits().getHits();
            count += hits.length;
            System.out.println("滚动第" + batch + "批结果总条数:" + count);

        }

        System.out.println("结束,总计:"+searchResponse.getHits().getTotalHits());

    }
}

综合考虑

  • 对于网页应用中的普通分页浏览,尤其是前几页,from+size足够。
  • 如果需要处理大数据集且允许一定的延迟,或者一次性获取所有结果,Scroll API 是更好的选择。
  • 对于深度分页且需要实时性较好的场景,应优先考虑search_after

优化方向

此外,针对大型分页查询的性能优化还可以包括:

  • 使用高效的过滤条件减少不必要的查询范围。
  • 考虑是否真的需要返回全部数据,或者能否通过汇总统计或其他方式减少数据传输量。
  • 设置合理的索引策略和分片大小,优化集群配置,如增加合适的内存缓冲区等。
相关推荐
珠海西格电力13 分钟前
零碳园区产业园管理系统的全场景源网荷储氢协同调度功能是如何实现的
大数据·运维·人工智能·物联网·能源
ai大模型中转api测评27 分钟前
解密 GPT-5.5:原生多模态架构如何重定义 AI 逻辑推理与精准制图
大数据·人工智能·gpt·架构·api
冷雨夜中漫步30 分钟前
Claude Code源码分析——Claude Code Agent Loop 详细设计文档
java·开发语言·人工智能·ai
直奔標竿36 分钟前
Java开发者AI转型第二十六课!Spring AI 个人知识库实战(五)——联网搜索增强实战
java·开发语言·人工智能·spring boot·后端·spring
数据皮皮侠AI39 分钟前
中国城市可再生能源数据集(2005-2021)|顶刊 Sci Data 11 种能源面板
大数据·人工智能·笔记·能源·1024程序员节
G311354227344 分钟前
如何用 QClaw 龙虾做一个规律作息健康助理 Agent
大数据·人工智能·ai·云计算
幂律智能1 小时前
零售行业合同管理数智化转型解决方案
大数据·人工智能·零售
华万通信king1 小时前
WorkBuddy知识库企业级搭建实战:从零到生产级别的完整路径
大数据·人工智能
智慧景区与市集主理人1 小时前
五一市集分账混乱?巨有科技智慧市集小程序实现统一收款、自动分账
大数据·科技·小程序
互联网志1 小时前
政策赋能校产融合 推动高校科技成果落地生根
大数据·人工智能·物联网