分页查询

关于 Elasticsearch 分页查询,这几个问题经常被问到

问题1:想请问下,一次性获取索引上的某个字段的所有值(100 万左右),除了把 max_result_window 调大 ,还有没有啥方法?

问题2:关于 es 的分页,每次拿 20 条展示在前台,然后点击下一页,在查询后面的20条数据,应该要怎么写?

问题3:From+size、Scroll、search_after 的本质区别和应用场景分别是什么?

From + size 分页查询

默认返回前10个匹配的匹配项。其中:
       ● from:未指定,默认值是 0,注意不是1,代表当前页返回数据的起始值。
       ● size:未指定,默认值是 10,代表当前页返回数据的条数。

如下指定条件查询和排序:

{"query": {"bool": {"must": [{"term": {"business_tag_id": "3"}}],"must_not": [],"should": []}},"from": 0,"size": 10,"sort": [],"aggs": {}
}

共返回 10 条数据。其中:
       ● from + size 两个参数定义了结果页面显示数据的内容。

From + size 查询优点:
       ● 支持随机翻页。

From + size 查询缺点:
       ● 受制于 max_result_window 设置,不能无限制翻页。
       ● 存在深度翻页问题,越往后翻页越慢。

From + size 查询适用场景:
       ● 非常适合小型数据集或者大数据集返回 Top N(N <= 10000)结果集的业务场景。
       ● 类似主流 PC 搜索引擎(谷歌、bing、百度、360、sogou等)支持随机跳转分页的业务场景。

深度翻页不推荐使用 From + size:
       ● Elasticsearch 会限制最大分页数,避免大数据量的召回导致性能低下。
       ● Elasticsearch 的 max_result_window 默认值是:10000。也就意味着:如果每页有 10 条数据,会最大翻页至 1000 页。

不推荐使用 from + size 做深度分页查询的核心原因:
       ● 搜索请求通常跨越多个分片,每个分片必须将其请求的命中内容以及任何先前页面的命中内容加载到内存中。
       ● 对于翻页较深的页面或大量结果,这些操作会显著增加内存和 CPU 使用率,从而导致性能下降或节点故障。

search_after 查询

search_after 查询本质:使用前一页中的一组排序值来检索匹配的下一页。

前置条件:使用 search_after 要求后续的多个请求返回与第一次查询相同的排序结果序列。也就是说,即便在后续翻页的过程中,可能会有新数据写入等操作,但这些操作不会对原有结果集构成影响。

如何实现呢?

可以创建一个时间点 Point In Time(PIT)保障搜索过程中保留特定事件点的索引状态。

Point In Time(PIT)是 Elasticsearch 7.10 版本之后才有的新特性。

PIT的本质:存储索引数据状态的轻量级视图。

如下示例能很好的解读 PIT 视图的内涵。

# 创建 PIT
POST kibana_sample_data_logs/_pit?keep_alive=1m# 获取数据量 14074
POST kibana_sample_data_logs/_count# 新增一条数据
POST kibana_sample_data_logs/_doc/14075
{"test":"just testing"
}# 数据总量为 14075
POST kibana_sample_data_logs/_count# 查询PIT,数据依然是14074,说明走的是之前时间点的视图的统计。
POST /_search
{"track_total_hits": true, "query": {"match_all": {}}, "pit": {"id": "48myAwEXa2liYW5hX3NhbXBsZV9kYXRhX2xvZ3MWM2hGWXpxLXFSSGlfSmZIaXJWN0dxUQAWdG1TOWFMTF9UdTZHdVZDYmhoWUljZwAAAAAAAAEN3RZGOFJCMGVrZVNndTk3U1I0SG81V3R3AAEWM2hGWXpxLXFSSGlfSmZIaXJWN0dxUQAA"}
}

有了 PIT,search_after 的后续查询都是基于 PIT 视图进行,能有效保障数据的一致性。

search_after 分页查询可以简单概括为如下几个步骤。

步骤 1:创建 PIT 视图,这是前置条件不能省。

# Step 1: 创建 PIT
POST kibana_sample_data_logs/_pit?keep_alive=5m

返回结果如下:

{"id" : "48myAwEXa2liYW5hX3NhbXBsZV9kYXRhX2xvZ3MWM2hGWXpxLXFSSGlfSmZIaXJWN0dxUQAWdG1TOWFMTF9UdTZHdVZDYmhoWUljZwAAAAAAAAEg5RZGOFJCMGVrZVNndTk3U1I0SG81V3R3AAEWM2hGWXpxLXFSSGlfSmZIaXJWN0dxUQAA"
}

keep_alive=5m,类似scroll的参数,代表视图保留时间是 5 分钟,超过 5 分钟执行会报错如下:

  "type" : "search_context_missing_exception","reason" : "No search context found for id [91600]"

步骤 2:创建基础查询语句,这里要设置翻页的条件。

# Step 2: 创建基础查询
GET /_search
{"size":10,"query": {"match" : {"host" : "elastic"}},"pit": {"id":  "48myAwEXa2liYW5hX3NhbXBsZV9kYXRhX2xvZ3MWM2hGWXpxLXFSSGlfSmZIaXJWN0dxUQAWdG1TOWFMTF9UdTZHdVZDYmhoWUljZwAAAAAAAAEg5RZGOFJCMGVrZVNndTk3U1I0SG81V3R3AAEWM2hGWXpxLXFSSGlfSmZIaXJWN0dxUQAA", "keep_alive": "1m"},"sort": [ {"response.keyword": "asc"}]
}

● 设置了PIT,检索时候就不需要再指定索引。
       ● id 是基于步骤1 返回的 id 值。
       ● 排序 sort 指的是:按照哪个关键字排序。

在每个返回文档的最后,会有两个结果值,如下所示:

 "sort" : ["200",4]

● 其中,“200”就是我们指定的排序方式:基于 {“response.keyword”: “asc”} 升序排列。

而 4 代表什么含义呢?
       ● 4 代表隐含的排序值,是基于_shard_doc 的升序排序方式。

官方文档把这种隐含的字段叫做:tiebreaker (决胜字段),tiebreaker 等价于_shard_doc。

tiebreaker 本质含义:每个文档的唯一值,确保分页不会丢失或者分页结果数据出现重复(相同页重复或跨页重复)。

步骤3:实现后续翻页。

# step 3 : 开始翻页
GET /_search
{"size": 10,"query": {"match" : {"host" : "elastic"}},"pit": {"id":  "48myAwEXa2liYW5hX3NhbXBsZV9kYXRhX2xvZ3MWM2hGWXpxLXFSSGlfSmZIaXJWN0dxUQAWdG1TOWFMTF9UdTZHdVZDYmhoWUljZwAAAAAAAAEg5RZGOFJCMGVrZVNndTk3U1I0SG81V3R3AAEWM2hGWXpxLXFSSGlfSmZIaXJWN0dxUQAA", "keep_alive": "1m"},"sort": [{"response.keyword": "asc"}],"search_after": [                                "200",4]
}

后续翻页都需要借助 search_after 指定前一页的最后一个文档的 sort 字段值。

如下代码所示:

  "search_after": [                                "200",4]

显然,search_after 查询仅支持向后翻页。

search_after 优点:
       ● 不严格受制于 max_result_window,可以无限制往后翻页。
ps:不严格含义:单次请求值不能超过 max_result_window;但总翻页结果集可以超过。

search_after 缺点:
       ● 只支持向后翻页,不支持随机翻页。

search_after 适用场景:
       ● 类似:今日头条分页搜索 https://m.toutiao.com/search;不支持随机翻页,更适合手机端应用的场景。

Scroll 遍历查询

相比于 From + size 和 search_after 返回一页数据,Scroll API 可用于从单个搜索请求中检索大量结果(甚至所有结果),其方式与传统数据库中游标(cursor)类似。

如果把 From + size 和 search_after 两种请求看做近实时的请求处理方式,那么 scroll 滚动遍历查询显然是非实时的。数据量大的时候,响应时间可能会比较长。

scroll 核心执行步骤如下:

步骤 1:指定检索语句同时设置 scroll 上下文保留时间。

实际上,scroll 已默认包含了 search_after 的PIT 的视图或快照功能。

从 Scroll 请求返回的结果反映了发出初始搜索请求时索引的状态,类似在那一个时刻做了快照。随后对文档的更改(写入、更新或删除)只会影响以后的搜索请求。

POST kibana_sample_data_logs/_search?scroll=3m
{"size": 100,"query": {"match": {"host": "elastic"}}
}

步骤 2:向后翻页继续获取数据,直到没有要返回的结果为止。

POST _search/scroll
{"scroll" : "3m","scroll_id":"FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFkY4UkIwZWtlU2d1OTdTUjRIbzVXdHcAAAAAAAGmkBZ0bVM5YUxMX1R1Nkd1VkNiaGhZSWNn"
}

scroll_id 值是步骤 1 返回的结果值。

scroll 查询优点:
       ● 支持全量遍历。
ps:单次遍历的 size 值也不能超过 max_result_window 大小。

scroll 查询缺点:
       ● 响应时间非实时。
       ● 保留上下文需要足够的堆内存空间。

scroll 查询适用场景:
       ● 全量或数据量很大时遍历结果数据,而非分页查询。
       ● 官方文档强调:不再建议使用scroll API进行深度分页。如果要分页检索超过 Top 10,000+ 结果时,推荐使用:PIT + search_after。

小结

● From+ size:需要随机跳转不同分页(类似主流搜索引擎)、Top 10000 条数据之内分页显示场景。

● search_after:仅需要向后翻页的场景及超过Top 10000 数据需要分页场景。

● Scroll:需要遍历全量数据场景 。

● max_result_window:调大治标不治本,不建议调过大。

● PIT:本质是视图。

聚合分析

什么是聚合分析

聚合分析是值ElasticSearch除搜索功能外提供的针对ElasticSearch数据做统计分析的功能
       ● 功能丰富:提供Bucket,Metric,Pipeline等多种分析方式,可以满足大部分的分析需求
       ● 实时性高:所有的计算结果都是及时返回的,而Hadoop等大数据系统一般都是T+1的。

聚合分类

名称 作用 对比Mysql
分桶类型 (Bucket) 满足特定条件的文档的集合 类似GROUP BY语法
指标分析类型(Metric) 计算最大值,最小值,平均值等 类似 COUNT 、 SUM() 、 MAX() 等统计方法
管道分析类型(Pipeline) 对聚合结果进行二次分析
矩阵分析类型(Matrix) 支持对多个字段的操作并提供一个结果矩阵

Bucket聚合分析

按照Bucket的分桶策略,常见的Bucket聚合分析如下:

策略 描述
Terms 最简单策略,如果是text类型,则按照分词后的结果分桶
Range 按照指定数值的范围来设定分桶规则
Date Range 通过指定日期的范围来设定分桶规则
Histogram 直方图,以固定间隔的策略来分割数据
Date Histogram 针对日期的直方图或者柱状图,是时序数据分析中常用的聚合分析类型

Terms:
       ● 最简单策略,如果是text类型,则按照分词后的结果分桶

{"size":0,//hits返回的数量,默认20条"aggs": {"可自定义分组名": { "terms": {"field": "指定字段","size": 3// 查询的数量}}}
}

Range:
       ● 按照指定数值的范围来设定分桶规则

{"size":0,//hits返回的数量,默认20条"aggs": {"可自定义分组名": {"range": {"field": "字段","ranges": [{"from": 10, // 大于等于"to": 20 // 小于},{"from": 20, // 大于等于"to": 30 // 小于},...]}}}
}

Date Range:
       ● 通过指定日期的范围来设定分桶规则

{"size":0,//hits返回的数量,默认20条"aggs": {"可自定义分组名": {"date_range": {"field": "字段","ranges": [{"from": "begin", //格式为:yyyy-MM-dd HH:mm:ss"to": "end" // 格式为:yyyy-MM-dd HH:mm:ss},{"from": "now-10d/d", //当前时间减去10天,格式为:yyyy-MM-dd HH:mm:ss"to": "now" // 当前时间,格式为:yyyy-MM-dd HH:mm:ss}]}}}
}

Histogram:
       ● 直方图,以固定间隔的策略来分割数据

{"size": 0, //hits返回的数量,默认20条"aggs": {"NAME": {"histogram": {"field": "字段","interval": 10, // 步长"extended_bounds": {"min": 10,// 最小值 x >= 10 "max": 40 // 最大值 x <= 40}}}}
}

Date Histogram:
       ● 针对日期的直方图或者柱状图,是时序数据分析中常用的聚合分析类型

{"size": 0, "aggs": {"NAME": {"date_histogram": {"field": "字段","interval": "day",// 维度"format": "yyyy-MM-dd",//格式化日期"extended_bounds": {"min": "最小值","max": "最大值"}}}}
}

interval:值有:year、month、week、day、hour、minute

Metric指标分析

计算最大值,最小值,平均值等,类似 COUNT 、 SUM() 、 MAX() 等统计方法。

单值分析

最大和最小:
       ● max:返回数值类字段的最大值
       ● min: 返回数值类字段的最小值

{"size": 0, "aggs": {"自定义分组名": {"max/min": {"field": "字段"}}}
}

平均值、求和:
       ● avg:返回数值类字段的平均值
       ● sum:返回数值类字段的总和

去重:
       ● cardinality: 是指不同数值的个数,类似SQL中的distinct count概念

多值分析

Stats:
       ● 返回一系列数值类型的统计值,包含min,max,avg,sum和count,被分析的字段只能是数字类型

Extended Stats:
       ● 对stats的扩展,包含了更多的统计数据,如方差,标准差等

top_hits:
       ● 一般用于分桶后获取桶内最匹配的顶部文档列表,即详情数据

聚合附加条件

filter:为聚合分析设定过滤条件。

聚合后排序

可以使用自带的关键数据进行排序,如下:
       ● _count: 文档数
       ● _key: 按照key值排序

Elasticsearch 分页查询聚合分析相关推荐

  1. ElasticSearch分页查询几种方式分析

    ElasticSearch分页查询几种方式分析 1 from+size 语句示例 # from+size浅分页 GET test/_search {"from": 10," ...

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

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

  3. ElasticSearch分页查询的3个坑

    点击上方"Java基基",选择"设为星标" 做积极的人,而不是积极废人! 每天 14:00 更新文章,每天掉亿点点头发... 源码精品专栏 原创 | Java ...

  4. Elasticsearch——分页查询FromSize VS scroll

    一:ES的存储和查询原理 Elasticsearch中数据都存储在分片中,当执行搜索时每个分片独立搜索后,数据再经过整合返回. 二:如何分页查询呢? (1)抛出需求问题 按照一般的查询流程来说,如果我 ...

  5. ElasticSearch分页查询四种解决方案与原理

    当你拼命想完成一件事的时候,你就不再是别人的对手,或者说得更确切一些,别人就不再是你的对手了,不管是谁,只要下了这个决心,他就会立刻觉得增添了无穷的力量,而他的视野也随之开阔了.--<基督山伯爵 ...

  6. ElasticSearch 分页查询及深度分页原理与实现

    查询流程 查询阶段 在初始化查询阶段(query phase),查询被向索引中的每个分片副本(原本或副本)广播.每个分片在本地执行搜索并且建 立了匹配 document 的优先队列(priority ...

  7. Elasticsearch分页查询FromSize vs scroll vs search_after

    背景 Elasticsearch 是一个实时的分布式搜索与分析引擎,被广泛用来做全文搜索.结构化搜索.分析.在使用过程中,有一些典型的使用场景,比如分页.遍历等.在使用关系型数据库中,我们被告知要注意 ...

  8. MySQL 数据库 分页查询/聚合查询

    引言 在本篇博客简单介绍一下分页查询以及聚合查询简单操作. 分页查询 在MySQL中,分页查询一般都是使用limit子句实现,limit子句声明如下: SELECT * FROM table LIMI ...

  9. Elasticsearch分页查询Fromamp;Size VS scroll

    对于ES来说,按照一般的查询流程来说,如果我想查询数据: 1 客户端请求发给某个节点 2 节点转发给个个分片,查询每个分片上的前10条 3 结果返回给节点,整合数据,提取前10条 4 返回给请求客户端 ...

最新文章

  1. 建立一个php 基础类
  2. 数博前沿 | 企业数据应用:聚焦场景,打通“最后一公里”
  3. php自动断词,PHP自动分页、防止英文单词被截段、去除HTML代码
  4. 直接拖动元器件_电子元器件常规检测和判断
  5. MyBatis:事务回滚
  6. Tomcat 报错 java.net.connectexception:拒绝连接 解决办法
  7. 诗与远方:无题(四十三)- 幼稚肤浅
  8. 关于Python的一些学习笔记(小白式笔记,持续更新)
  9. AcWing 1057. 股票买卖 IV
  10. spring boot mybatis 整合_两大热门框架 Spring 与 Mybatis 如何整合呢?
  11. 光线如何从宇宙黑暗时代逃逸:黑洞让宇宙变光明
  12. 机器学习实战——KNN及部分函数注解
  13. Linux下Tomcat使用80端口
  14. 使用C语言创建顺序表
  15. linux之ab测试
  16. 成功的发行模式(标题 我自己改的 转至 敏思博客)
  17. java.time.format.DateTimeParseException: Text ‘xxxx-xx-xx xx:xx:xx‘ could not be parsed at index 10
  18. hive drop表恢复手册
  19. 世界杯“诈骗杯”?小心这些就对了
  20. 一些关于HTML与CSS的总结与实际应用

热门文章

  1. 使用Halcon进行颜色反转
  2. 早报 | 阿里发布最新季度财报;传滴滴拟裁员25%;贾跃亭时隔90天首发声
  3. 域名备案号和密码忘记找回指导与坑
  4. 关于自动拣DD的外挂文件
  5. Android 动画 - ScaleAnimation 缩放动画使用(附图)
  6. [linux]全志H3 nanopi 点亮ST7789VW IPS屏
  7. nonnull和nullable
  8. devc++编译时 devc undefind reference to '_imp_htonl'
  9. 个人APP开发者如何对接聚合广告SDK平台?
  10. 疫情期间网络攻击花样翻新,全年 81748 起安全事件背后暗藏规律