ElasticSearch入门之es分页, size+from浅分页, scroll深分页 11

1. 先导入一部分数据

DELETE us
POST /_bulk
{ "create": { "_index": "us", "_type": "tweet", "_id": "1" }}
{ "email" : "john@smith.com", "name" : "John Smith", "username" : "@john" }
{ "create": { "_index": "us", "_type": "tweet", "_id": "2" }}
{ "email" : "mary@jones.com", "name" : "Mary Jones", "username" : "@mary" }
{ "create": { "_index": "us", "_type": "tweet", "_id": "3" }}
{ "date" : "2014-09-13", "name" : "Mary Jones", "tweet" : "Elasticsearch means full text search has never been so easy", "user_id" : 2 }
{ "create": { "_index": "us", "_type": "tweet", "_id": "4" }}
{ "date" : "2014-09-14", "name" : "John Smith", "tweet" : "@mary it is not just text, it does everything", "user_id" : 1 }
{ "create": { "_index": "us", "_type": "tweet", "_id": "5" }}
{ "date" : "2014-09-15", "name" : "Mary Jones", "tweet" : "However did I manage before Elasticsearch?", "user_id" : 2 }
{ "create": { "_index": "us", "_type": "tweet", "_id": "6" }}
{ "date" : "2014-09-16", "name" : "John Smith",  "tweet" : "The Elasticsearch API is really easy to use", "user_id" : 1 }
{ "create": { "_index": "us", "_type": "tweet", "_id": "7" }}
{ "date" : "2014-09-17", "name" : "Mary Jones", "tweet" : "The Query DSL is really powerful and flexible", "user_id" : 2 }
{ "create": { "_index": "us", "_type": "tweet", "_id": "8" }}
{ "date" : "2014-09-18", "name" : "John Smith", "user_id" : 1 }
{ "create": { "_index": "us", "_type": "tweet", "_id": "9" }}
{ "date" : "2014-09-19", "name" : "Mary Jones", "tweet" : "Geo-location aggregations are really cool", "user_id" : 2 }
{ "create": { "_index": "us", "_type": "tweet", "_id": "10" }}
{ "date" : "2014-09-20", "name" : "John Smith", "tweet" : "Elasticsearch surely is one of the hottest new NoSQL products", "user_id" : 1 }
{ "create": { "_index": "us", "_type": "tweet", "_id": "11" }}
{ "date" : "2014-09-21", "name" : "Mary Jones", "tweet" : "Elasticsearch is built for the cloud, easy to scale", "user_id" : 2 }
{ "create": { "_index": "us", "_type": "tweet", "_id": "12" }}
{ "date" : "2014-09-22", "name" : "John Smith", "tweet" : "Elasticsearch and I have left the honeymoon stage, and I still love her.", "user_id" : 1 }
{ "create": { "_index": "us", "_type": "tweet", "_id": "13" }}
{ "date" : "2014-09-23", "name" : "Mary Jones", "tweet" : "So yes, I am an Elasticsearch fanboy", "user_id" : 2 }
{ "create": { "_index": "us", "_type": "tweet", "_id": "14" }}
{ "date" : "2014-09-24", "name" : "John Smith", "tweet" : "How many more cheesy tweets do I have to write?", "user_id" : 1 }

2. size+from浅分页

按照一般的查询流程来说,如果我想查询前10条数据:

  1. 客户端请求发送给某个节点
  2. 节点转发给各个分片,查询每个分片上的前10条中的部分数据
  3. 结果返回给节点, 整合数据,提取前10条
  4. 返回给请求客户端
  • 命令符是使用fromsize两个关键字, from定义了目标数据的偏移量(每页的其实索引), size定义每页显示条数
GET /us/_search?pretty
{
  "from" : 0 , "size" : 10
}

GET /us/_search?pretty
{
  "from" : 10 , "size" : 10
}
  • 这种浅分页只适合少量数据, 因为隋from增大,查询的时间就会越大;而且数据越大,查询的效率指数下降.
  • 优点: from+size在数据量不大的情况下,效率比较高.
  • 缺点: 在数据量非常大的情况下,from+size分页会把全部记录加载到内存中,这样做不但运行速递特别慢,而且容易让es出现内存不足而挂掉.

3. scroll深分页

对于上面介绍的浅分页,当Elasticsearch响应请求时,它必须确定docs的顺序,排列响应结果。

如果请求的页数较少(假设每页20个docs), Elasticsearch不会有什么问题,但是如果页数较大时,比如请求第20页,Elasticsearch不得不取出第1页到第20页的所有docs,再去除第1页到第19页的docs,得到第20页的docs。

解决的方式就是使用scroll,scroll就是维护了当前索引段的一份快照信息–缓存(这个快照信息是你执行这个scroll查询时的快照)。

可以把 scroll 分为初始化遍历两步:
1、初始化时将所有符合搜索条件的搜索结果缓存起来,可以想象成快照;
2、遍历时,从这个快照里取数据;

  • 初始化
# 初始化的时候就像是普通的search一样
# 其中的scroll=3m代表当前查询的数据缓存3分钟
# Size:3 代表当前查询3条数据
GET us/_search?scroll=3m
{
  "query": {"match_all": {}},
   "size": 3
}
  • 遍历
    在遍历时候,拿到上一次遍历中的_scroll_id,然后带scroll参数,重复上一次的遍历步骤,知道返回的数据为空,就表示遍历完成
    GET /_search/scroll
    {
      "scroll" : "1m",
      "scroll_id" : "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAAPXFk0xN1BmSnlVUldhYThEdWVzZ19xbkEAAAAAAAAAIxZuQWVJU0VSZ1JzcVZtMGVYZ3RDaFlBAAAAAAAAA9oWTVZOdHJ2cXBSOU9wN3c1dk5vcWd4QQAAAAAAAAPYFk0xN1BmSnlVUldhYThEdWVzZ19xbkEAAAAAAAAAIhZuQWVJU0VSZ1JzcVZtMGVYZ3RDaFlB"
    }

【注意】:每次都要传参数scroll,刷新搜索结果的缓存时间,另外不需要指定index和type(不要把缓存的时时间设置太长,占用内存

4. 浅分页和深分页对比

浅分页,每次查询都会去索引库(本地文件夹)中查询pageNum*page条数据,然后截取掉前面的数据,留下最后的数据。 这样的操作在每个分片上都会执行,最后会将多个分片的数据合并到一起,再次排序,截取需要的。

深分页,可以一次性将所有满足查询条件的数据,都放到内存中。分页的时候,在内存中查询。相对浅分页,就可以避免多次读取磁盘

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
Elasticsearch 中,分页功能的使用需要考虑到性能问题。一般来说,建议不要使用过分页,以避免对 Elasticsearch 的性能造成负面影响。 以下是在 Elasticsearch 中使用分页的方法: 1. 使用 scroll API 进行分页查询 scroll API 可以在内存中存储搜索上下文,而不是在每个请求之间重新计算。这使得在大数据集上进行分页查询变得更加有效。 示例代码: ``` SearchRequest searchRequest = new SearchRequest("indexName"); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.query(QueryBuilders.matchAllQuery()); searchSourceBuilder.size(100); searchRequest.source(searchSourceBuilder); SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); String scrollId = searchResponse.getScrollId(); SearchHit[] searchHits = searchResponse.getHits().getHits(); while (searchHits != null && searchHits.length > 0) { SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId); scrollRequest.scroll(TimeValue.timeValueMinutes(1L)); SearchResponse scrollResponse = client.scroll(scrollRequest, RequestOptions.DEFAULT); scrollId = scrollResponse.getScrollId(); searchHits = scrollResponse.getHits().getHits(); // Do something with searchHits } ClearScrollRequest clearScrollRequest = new ClearScrollRequest(); clearScrollRequest.addScrollId(scrollId); client.clearScroll(clearScrollRequest, RequestOptions.DEFAULT); ``` 在上面的示例中,size 参数设置为 100,表示每次检索返回 100 个结果。scroll API 的 scroll 参数设置为 1 分钟,表示在这段时间内保持搜索上下文。 2. 使用 search_after 参数进行分页查询 search_after 参数可以用来指定上一次搜索的最后一个结果,以便从下一个结果开始进行分页查询。 示例代码: ``` SearchRequest searchRequest = new SearchRequest("indexName"); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.query(QueryBuilders.matchAllQuery()); searchSourceBuilder.size(100); searchRequest.source(searchSourceBuilder); SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); SearchHit[] searchHits = searchResponse.getHits().getHits(); while (searchHits != null && searchHits.length > 0) { SearchHit lastHit = searchHits[searchHits.length - 1]; searchSourceBuilder.searchAfter(lastHit.getSortValues()); searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); searchHits = searchResponse.getHits().getHits(); // Do something with searchHits } ``` 在上面的示例中,size 参数设置为 100,表示每次检索返回 100 个结果。search_after 参数使用上一次搜索的最后一个结果的排序值。 总之,分页查询在 Elasticsearch 中的实现需要考虑性能问题,建议使用 scroll API 或 search_after 参数来实现。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值