博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
elasticsearch 分页查询实现方案
阅读量:5978 次
发布时间:2019-06-20

本文共 2886 字,大约阅读时间需要 9 分钟。

hot3.png

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 跳转到下一页。

转载于:https://my.oschina.net/xhx6616/blog/1528454

你可能感兴趣的文章
Python - - 项目实战 -- pygame 快速入门
查看>>
设置树莓派开机自动运行代码
查看>>
F - The Circumference of the Circle
查看>>
matlab练习程序(中值滤波)
查看>>
恋愛SLG-「猫セット」ゲットチャレンジ!
查看>>
OpenGL帧缓存对象(FBO:Frame Buffer Object)(转载)
查看>>
茶觉 | “治愈”的白牡丹
查看>>
JAVA学习笔记--初始化与清理
查看>>
hdu1789
查看>>
在EditText里插入图片,基于图库选择之后
查看>>
多输入的等价类划分以及测试
查看>>
3、编写一个prod()函数,可以接受一个list并利用reduce()求积
查看>>
mybatis_基础篇
查看>>
php的filesystem基本函数的学习(1)
查看>>
linux下SSH远程连接服务慢解决方案
查看>>
IBM X3650 M3服务器上RAID配置实战
查看>>
八、IO优化(1)磁盘簇
查看>>
Win2012R2 VDI RemoteFX Grid K2测试
查看>>
LoadRunner如何和jenkins结合使用
查看>>
VMware vSphere 5.1 群集深入解析(十七)-DPM计算推荐
查看>>