1. from+size 实现分页

from表示从第几行开始,size表示查询多少条文档。from默认为0,size默认为10,

注意:size的大小不能超过index.max_result_window这个参数的设置,默认为10,000。

如果搜索size大于10000,需要设置index.max_result_window参数

PUT _settings
{
"index": {
"max_result_window": "10000000"
}
}

内部执行原理:

示例:有三个节点node1、node2、node3,每个节点上有2个shard分片

node1 node2 node3
shard1 shard3 shard5
shard2 shard4 shard6
1.client发送分页查询请求到node1(coordinating node)上,node1建立一个大小为from+size的优先级队列来存放查询结果;
2.node1将请求广播到涉及到的shards上;
3.每个shards在内部执行查询,把from+size条记录存到内部的优先级队列(top N表)中;
4.每个shards把缓存的from+size条记录返回给node1;
5.node1获取到各个shards数据后,进行合并并排序,选择前面的 from + size 条数据存到优先级队列,以便 fetch 阶段使用。

各个分片返回给 coordinating node 的数据用于选出前 from + size 条数据,所以,只需要返回唯一标记 doc 的 _id 以及用于排序的 _score 即可,这样也可以保证返回的数据量足够小。

coordinating node 计算好自己的优先级队列后,query 阶段结束,进入 fetch 阶段。

from+size在深度分页时,会带来严重的性能问题:

CPU、内存、IO、网络带宽

数据量越大,越往后翻页,性能越低

2.scroll

可以把 scroll 理解为关系型数据库里的 cursor,因此,scroll 并不适合用来做实时搜索,而更适用于后台批处理任务,比如群发。

可以把 scroll 分为初始化和遍历两步,

初始化时将所有符合搜索条件的搜索结果缓存起来,可以想象成快照,

遍历时,从这个快照里取数据,也就是说,在初始化后对索引插入、删除、更新数据都不会影响遍历结果。

1.初始化:

POST http://192.168.18.230:9200/bill/bill/_search?scroll=3m
{
"query": { "match_all": {}},
"size": 10
}

参数 scroll,表示暂存搜索结果的时间

返回一个 _scroll_id,_scroll_id 用来下次取数据用

2.遍历:

POST http://192.168.18.230:9200/_search?scroll=3m
{
"scroll_id": "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAHRCFi1BLWIzSHdhUkl1cC1rcjBueVhJZUEAAAAAAAB0QRYtQS1iM0h3YVJJdXAta3IwbnlYSWVBAAAAAAAAdEQWLUEtYjNId2FSSXVwLWtyMG55WEllQQAAAAAAAHRDFi1BLWIzSHdhUkl1cC1rcjBueVhJZUEAAAAAAAB0RRYtQS1iM0h3YVJJdXAta3IwbnlYSWVB"
}

这里的 scroll_id 即 上一次遍历取回的 _scroll_id 或者是初始化返回的 _scroll_id,同样的,需要带 scroll 参数。

注意,每次都要传参数 scroll,刷新搜索结果的缓存时间。另外,不需要指定 index 和 type。

3.search_after

官网上的说明:

The Scroll api is recommended for efficient deep scrolling but scroll contexts are costly and it is not recommended to use it for real time user requests.
The search_after parameter circumvents this problem by providing a live cursor. The idea is to use the results from the previous page to help the retrieval of the next page.

Scroll 被推荐用于深度查询,但是contexts的代价是昂贵的,不推荐用于实时用户请求,而更适用于后台批处理任务,比如群发。

search_after 提供了一个实时的光标来避免深度分页的问题,其思想是使用前一页的结果来帮助检索下一页。

search_after 需要使用一个唯一值的字段作为排序字段,否则不能使用search_after方法

推荐使用_uid 作为唯一值的排序字段

GET twitter/tweet/_search
{
"size": 10,
"query": { "match_all": {}},
"sort": [
{"date": "asc"},
{"_uid": "desc"}
]
}

每一条返回记录中会有一组 sort values ,查询下一页时,在search_after参数中指定上一页返回的 sort values

GET twitter/tweet/_search
{
"size": 10,
"query": { "match_all": {}},
"search_after": [1463538857, "tweet#654323"],
"sort": [
{"date": "asc"},
{"_uid": "desc"}
]
}

注意:search_after不能自由跳到一个随机页面,只能按照 sort values 跳转到下一页

4.总结

  • 深度分页不管是关系型数据库还是Elasticsearch还是其他搜索引擎,都会带来巨大性能开销,特别是在分布式情况下。
  • 有些问题可以考业务解决而不是靠技术解决,比如很多业务都对页码有限制,google 搜索,往后翻到一定页码就不行了。
  • scroll 并不适合用来做实时搜索,而更适用于后台批处理任务,比如群发。
  • search_after不能自由跳到一个随机页面,只能按照 sort values 跳转到下一页。
      </div>
</div>
posted @
2019-05-06 14:03 
星朝 
阅读(...) 
评论(...) 
编辑 
收藏

elasticsearch 分页查询实现方案的更多相关文章

  1. elasticsearch 分页查询实现方案——Top K+归并排序

    elasticsearch 分页查询实现方案 1. from+size 实现分页 from表示从第几行开始,size表示查询多少条文档.from默认为0,size默认为10,注意:size的大小不能超 ...

  2. Elasticsearch 分页查询

    目录 前言 from + size search after scroll api 总结 参考资料 前言 我们在实际工作中,有很多分页的需求,商品分页.订单分页等,在MySQL中我们可以使用limit ...

  3. 真正高效的SQLSERVER分页查询(多种方案)

    Sqlserver数据库分页查询一直是Sqlserver的短板,闲来无事,想出几种方法,假设有表ARTICLE,字段ID.YEAR...(其他省略),数据53210条(客户真实数据,量不大),分页查询 ...

  4. Elasticsearch——分页查询From&Size VS scroll

    Elasticsearch中数据都存储在分片中,当执行搜索时每个分片独立搜索后,数据再经过整合返回.那么,如果要实现分页查询该怎么办呢? 更多内容参考Elasticsearch资料汇总 按照一般的查询 ...

  5. ElasticSearch—分页查询

    ElasticSearch查询—分页查询详解 Elasticsearch中数据都存储在分片中,当执行搜索时每个分片独立搜索后,数据再经过整合返回.那么,如何实现分页查询呢? 按照一般的查询流程来说,如 ...

  6. ElasticSearch——分页查询

    前言 ElasticSearch实现分页查询,有3种方式,他们在数据查询中各自占据着不同的优势,因此在搜索引擎的数据分页过程中,如何更好地利用各自的优势来进行数据查询是一个非常重要的过程. 传统分页( ...

  7. Elasticsearch分页查询

    global index global CLIENT index = "guajibao-ipused-2019.10.13" CLIENT = Elasticsearch(hos ...

  8. elasticsearch查询之大数据集分页查询

    一. 要解决的问题 search命中的记录特别多,使用from+size分页,直接触发了elasticsearch的max_result_window的最大值: { "error" ...

  9. 基于ArcGISServer进行分页矢量查询的方案进阶

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.    背景 在空间查询中,我们对查询结果要求以分页形式进行展示.G ...

随机推荐

  1. poj 2135 Farm Tour 【无向图最小费用最大流】

    题目:id=2135" target="_blank">poj 2135 Farm Tour 题意:给出一个无向图,问从 1 点到 n 点然后又回到一点总共的最短路 ...

  2. 杂项:Kafka

    ylbtech-杂项:Kafka Kafka是由Apache软件基金会开发的一个开源流处理平台,由Scala和Java编写.Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站 ...

  3. golang iris html/temple

    在使用golang的模板语法的过程中遇见自动转义问题(或者以我的理解下发的富文本html代码不是template.html类型,而是string类型),需要强制转型 func unescaped(x ...

  4. 什么是递归?用十进制转二进制的Python函数示例说明

    先上用Python写的十进制转二进制的函数代码: def Dec2Bin(dec): result = '' if dec: result = Dec2Bin(dec//2) return resul ...

  5. AtCoder Beginner Contest 054

    1. A - One Card Poker 水题,直接输出大小. 2. B - Template Matching 暴力,每个位置枚举,比较. 3. C - One-stroke Path n的大小只 ...

  6. B - Expression

    Problem description Petya studies in a school and he adores Maths. His class has been studying arith ...

  7. Promise API 简介

    Promise API 简介 译者注: 到处是回调函数,代码非常臃肿难看, Promise 主要用来解决这种编程方式, 将某些代码封装于内部. Promise 直译为"承诺",但一 ...

  8. JavaScript实现数字时钟功能

    <html> <head> <meta charset="utf-8"> <title>无标题文档</title> &l ...

  9. [ Java ] [ JUnit ] [ Eclipse ] coverage

    官方資訊: https://www.eclemma.org/ - 簡短使用範例說明: https://dzone.com/articles/java-code-coverage-in-eclipse ...

  10. 三维投影总结:数学原理、投影几何、OpenGL教程、我的方法

    如果要得到pose视图,除非有精密的测量方法,否则进行大量的样本采集时很耗时耗力的.可以采取一些取巧的方法,正如A Survey on Partial of 3d shapes,描述的,可以利用已得到 ...