作者:碳酸钙baby_849 | 来源:互联网 | 2024-11-20 10:33
本文详细介绍了Elasticsearch中的分页查询机制,包括基本的分页查询流程、'from-size'浅分页与'scroll'深分页的区别及应用场景,以及两者在性能上的对比。
Elasticsearch 分页查询概述
在Elasticsearch中,分页查询是一种常见的需求,特别是在处理大量数据时。通常,分页查询的过程如下:
- 客户端向集群中的任意节点发送请求。
- 该节点将请求转发至各个分片,每个分片返回指定数量的结果。
- 节点收集所有分片返回的数据,合并并排序,最后返回给客户端。
当需要获取特定范围的数据时,例如第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'分页以提高查询效率。