热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Elasticsearch分页查询策略详解

本文详细介绍了Elasticsearch中的分页查询机制,包括基本的分页查询流程、'from-size'浅分页与'scroll'深分页的区别及应用场景,以及两者在性能上的对比。

Elasticsearch 分页查询概述


在Elasticsearch中,分页查询是一种常见的需求,特别是在处理大量数据时。通常,分页查询的过程如下:



  1. 客户端向集群中的任意节点发送请求。

  2. 该节点将请求转发至各个分片,每个分片返回指定数量的结果。

  3. 节点收集所有分片返回的数据,合并并排序,最后返回给客户端。


当需要获取特定范围的数据时,例如第10条到第20条记录,就需要使用分页查询功能。



'from-size' 浅分页


'from-size'分页是一种简单的分页方式,通过设置'from'参数来指定起始位置,'size'参数来指定返回的记录数。例如,查询前10条记录的请求如下:


{
"from": 0,
"size": 10,
"query": {
"term": {
"user": "kimchy"
}
}
}

这种方式虽然简单,但随着分页深度的增加,性能会显著下降。测试表明,随着'from'值的增大,查询时间也会相应增加,尤其是在数据量较大的情况下。



'scroll' 深分页


'scroll'分页主要用于一次性检索大量数据,类似于数据库中的游标。它通过维护一个快照来记录当前读取的位置,确保后续查询能够快速继续。使用'scroll'时,首先发起一个搜索请求,并获取一个'_scroll_id',之后使用这个ID继续检索:


curl -XGET 'localhost:9200/twitter/tweet/_search?scroll=1m' -d '{"query": {"match": {"title": "elasticsearch"}}}'

然后使用返回的'_scroll_id'继续检索:


curl -XGET 'localhost:9200/_search/scroll?scroll=1m&scroll_id=c2Nhbjs2OzM0NDg1ODpzRlBLc0FXNlNyNm5JWUc1'

'_scroll_id'是一个经过Base64编码的字符串,包含了查询的相关信息。'scroll'分页在处理大数据集时表现出色,因为它避免了重复查询和数据剔除的过程。



性能测试


为了比较'from-size'和'scroll'分页的性能,我们进行了如下测试。首先,使用Java客户端初始化Elasticsearch连接:



org.elasticsearch
elasticsearch
5.5.1


private static TransportClient client;
private static String INDEX = "index_name";
private static String TYPE = "type_name";

public static TransportClient init() {
Settings settings = Settings.builder()
.put("client.transport.sniff", true)
.put("cluster.name", "cluster_name")
.build();
client = new PreBuiltTransportClient(settings)
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("localhost"), 9300));
return client;
}

public static void main(String[] args) {
TransportClient client = init();
// 使用client执行查询
}

以下是'from-size'分页的测试代码:


System.out.println("from-size模式启动!");
Date begin = new Date();
long count = client.prepareCount(INDEX).setTypes(TYPE).execute().actionGet().getCount();
SearchRequestBuilder requestBuilder = client.prepareSearch(INDEX).setTypes(TYPE).setQuery(QueryBuilders.matchAllQuery());

for (int i = 0, sum = 0; sum SearchResponse respOnse= requestBuilder.setFrom(i * 50000).setSize(50000).execute().actionGet();
sum += response.getHits().hits().length;
System.out.println("总量" + count + " 已经查到" + sum);
}

Date end = new Date();
System.out.println("耗时: " + (end.getTime() - begin.getTime()));

以下是'scroll'分页的测试代码:


System.out.println("scroll模式启动!");
begin = new Date();
SearchResponse scrollRespOnse= client.prepareSearch(INDEX)
.setSearchType(SearchType.SCAN)
.setSize(10000)
.setScroll(TimeValue.timeValueMinutes(1))
.execute().actionGet();
count = scrollResponse.getHits().getTotalHits();

for (int i = 0, sum = 0; sum scrollRespOnse= client.prepareSearchScroll(scrollResponse.getScrollId())
.setScroll(TimeValue.timeValueMinutes(8))
.execute().actionGet();
sum += scrollResponse.getHits().hits().length;
System.out.println("总量" + count + " 已经查到" + sum);
}

end = new Date();
System.out.println("耗时: " + (end.getTime() - begin.getTime()));

测试结果显示,在33万多条数据的情况下,'scroll'分页的性能远优于'from-size'分页。对于大数据量的操作,建议使用'scroll'分页以提高查询效率。


推荐阅读
author-avatar
碳酸钙baby_849
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有