elasticsearch日期范围查询_elastic查看日志
如何用 Node.js 和 Elasticsearch 构建搜索引擎
select 在 Custom Label 输入域中输入字符串以更改显示标签。Elasticsearch 对软硬件要求比较灵活。虽然建议线上环境采用 64GB 内存,和尽可能多 CPU 系统配置,但其在一个资源受限的系统中依然可以很好地运行(前提是你的数据集不大)。
elasticsearch日期范围查询_elastic查看日志
elasticsearch日期范围查询_elastic查看日志
高可用 Elasticsearch 集群的分片管理 (Shard)
}{一个 shard 本质上就是一个 Lucene 索引,也是 Elasticsearch 分布式化 Lucene 的关键抽象,是 Elasticsearch 管理 Lucene 文件的最小单位。
auto - 随机生成密码。所以,Elasticsearch 提供了大量的接口,可以对集群内的 shard 进行管理。
在一些特别的情况下,例如发现大部分热点数据集中在几个,可以考虑手工 move 一下。
如果不提供参数调用该 api,Elasticsearch 返回个 unassigned shard 未分配的原因。
在索引过程中,Elasticsearch 首先在 primary shard 上执行索引作,之后将作发送到 replica shards 执行,通过这种方式使 primary 和 replica 数据同步。
对于同一个分片的所有 replicas,Elasticsearch 在集群的全局状态里保存所有处于同步状态的分片,称为 in-sync copies。
如果修改作在 primary shard 执行成功,在 replica 上执行失败,则 primary 和 replica 数据就不在同步,这时 Elasticsearch 会将修改作失败的 replica 标记为 stale,并更新到集群状态里。
当由于某种原因,对于某个 shard 集群中可用数据只剩 stale 分片时,集群会处于 red 状态,并不会主动将 stale shard 提升为 primary shard,因为该 shard 的数据不是的。这时如果不得不将 stale shard 提升为主分片,需要人工介入:
当由于 lucene index 损坏或者磁盘故障导致某个分片的主副本都丢失时,为了能使集群恢复 green 状态,的方法是划分一个空 shard。
一定要慎用该作,会导致对应分片的数据完全清空。
但是 shard 管理并不是 “免费” 的,shard 数量过多会消耗更多的 cpu、内存资源,引发一系列问题,主要包括如下几个方面。
任一时刻,一个集群中只有一个是 , 负责维护集群的状态信息,而且状态的更新是在单线程中运行的,大量的 shard 会导致集群状态相关的修改作缓慢,比如创建索引、删除索引,更新 setting 等。
单个集群 shard 超过 10 万,这些作会明显变慢。集群在恢复过程中,会频繁更显状态,引起恢复过程漫长。
我们曾经在单个集群维护 30 多万分片,集群完全重启有时候需要2-4个小时的时间,对于业务来说是难以忍受的。
查询很多小分片会降低单个 shard 的查询时间,但是如果分片过多,会导致查询任务在队列中排队,最终可能会增加查询的整体时间消耗。
Elasticsearch 协调接收到查询后,会将查询分发到查询涉及的所有 shard 并行执行,之后协调对各个 shard 的查询结果进行归并。
如果有很多小分片,增加协调的内存压力,同时会增加整个集群的 cpu 压力,甚至发生拒绝查询的问题。因为我们经常会设置参与搜索作的分片数上限,以保护集群资源和稳定性,分片数设置过大会更容易触发这个上限。
Elasticsearch 通过 AllocationDecider 策略来控制 shard 在集群内上的分布。
当使用 cluster.routing.allocation.balance.shard 和 index.routing.allocation.total_shards_per_node 不能使分片平衡时,就需要通过该参数来控制分片的分布。
所以,我们的经验是: 创建索引时,尽量将该值设置的小一些,以使索引的 shard 比较平均的分布到集群内的所有。
但是也要使个别离线时,分片能分配到在线,对于有 10 个几点的集群,如果单个索引的主副本分片总数为 10,如果将该参数设置成 1,当一个离线时,集群就无法恢复成 Green 状态了。
所以我们的建议一般是保证一个离线后,也可以使集群恢复到 Green 状态。
Elasticsearch 内部的平衡策略都是基于 shard 数量的,所以在运行一段时间后,如果不同索引的 shard 物理大小距很大,最终会出现磁盘使用不平衡的情况。
所以,目前来说避免该问题的以办法是让集群内的 shard 物理大小尽量保持相近。
主对 shard 的管理是一种代价相对比较昂贵的作,因此在满足需求的情况下建议尽量减少 shard 数量,将分片数量和分片大小控制在合理的范围内,可以避免很多问题。
下一节我们将介绍 分片内部的段合并 相关问题。
Elasticsearch 分组聚合查询(bucket) --- 2022-04-03
Elasticsearch桶聚合,目的就是数据分组,先将数据按指定的条件分成多个组,然后对每一个组进行统计。 组的概念跟桶是等同的,在ES中统一使用桶(bucket)这个术语。
ES桶聚合的作用跟SQL的group by的作用是一样的,区别是ES支持更加强大的数据分组能力,SQL只能根据字段的值进行分组,分组的数量跟字段的值的数量相等,例如: group by 店铺id, 去掉重复的店铺ID后,有多少个店铺就有多少个分组。
ES常用的桶聚合如一般来说,增加主分片数量可以增加写入速度和查询速度,因为数据分布到了更多的,可以利用更多的计算和 IO 资源。增加副分片数量可以提升查询速度,并发的查询可以在多个分片之间轮询。下:
Terms聚合 - 类似SQL的group by,根据字段值分组
Histogram聚合 - 根据数值间隔分组,例如: 价格按100间隔分组,0、100、200、300等等
Date histogram聚合 - 根据时间间隔分组,例如:按月、按天、按小时分组
Range聚合 - 按数值范围分组,例如: 0-150一组,150-200一组,200-500一组。
terms聚合的作用跟SQL中group by作用一样,都是根据字段值对数据进行分组(分桶),字段值相等的文档都分到同一个桶内。
返回结果:
2.Histogram聚合
返回结果:
3.Date histogram聚合
类似histogram聚合,区别是Date histogram可以很好的处理时间类型字段,主要用于根据时间、日期分桶的场景。
返回结果:
4.Range聚合
range聚合,按数值范围分桶。
返回结果:
大家仔细观察的话,发现range分桶,默认key的值不太友好,尤其开发的时候,不知道key长什么样子,处理起来比较麻烦,我们可以为每一个分桶指定一个有意义的名字。
例提示:桶聚合一般不单独使用,都是配合指标聚合一起使用,对数据分组之后肯定要统计桶内数据,在ES中如果没有明确指定指标聚合,默认使用Value Count指标聚合,统计桶内文档总数。子:
5.综合例子
前面的例子,都是单独使用aggs聚合语句,代表直接统计所有的文档,实际应用中,经常需要配合query语句,先搜索目标文档,然后使用aggs聚合语句对搜索结果进行统计分析。
例子:
聚合查询支持多层嵌套。
Elasticsearch排序
将仪表板和其他保存的对象组织到有意义的类别中。下面的例子就容易做到:
该查询会返回所有在title字段上至少命中一个词项的文档,并且基于section数据排序
也可以通过添加查询sort部分的missing属性为那些section字段缺失的文档定制排序行为
某些文档的release-dates字段里面储存了多个电影上映日期(同一部电影在不同的上映日期不同)我们可以构造查询请求:
例子中 es将基于每个文档的release_dates字段的最小值进行排序
mode参数可以设置为以上值:
后面两个选项只对数值类型有效
es提供了基于坐标系数据的排序,我们通过一个实例了解这种类型的排序
例如,要查找特点里离自己最近的一个机构
我们使用下面的这个映射:
查询如图:
我们可以看到,返回结果包含这个值:“sort”:[0.0]这是因为返回文档的地理坐标和查询中的坐标匹配
还可以设置mode属性为max,min,g
例如g代表:此时基于字段中的地理位置坐标与查询坐标的距离的均值排序
继续嵌套对GET /forum/article/_search象的排序, 对以下两种情形都适用 :
查询:
查询返回结果按照嵌套对象的usert字段最小值降序
如果将子文档视为一种数据类型,则可以将查询简化为如下形式:
当我们使用对象类型时,可以简化查询,这是因为整个对象结构被当成一个lucene文档进行储存
有些时候,使用 nested_path 属性会更加便捷
按照下面的方式构造查询:
我们也可以使用 nested_filter 参数,改参数只对嵌套文档有效,利用这个参数,我们可以在排序前就已经通过一个过滤器在检索期排除了某些文档,而不是检索结果文档集中过滤它们
(注:内容整理自《深入理解Elasticsearch》)
Elasticsearch:painless script 语法基础和实战
例子:摘要: Elasticsearch , Ja
script是Elasticsearch的拓展功能,通过定制的表达式实现已经预设好的API无法完成的个性化需求,比如完成以下作
语法都遵循相同的模式
其中三要素功能如下
使用script脚本修改某文档的某个字段,先插入一条文档
注意在kibiban客户端带上 _update ,否则相当于覆盖整个文档,新建了一个含有script字段的文档。本例中将pr字段修改为333,如果是带有单引号的'333'则修改为字符串数据,字符串还可以在Elasticsearch索引中创建可视化并聚合数据存储。使用 转义
只要inline脚本中的内容出现些许不一样就需要重新编译,因此的方法是 把inline中固定的部分编译一次,变量命名放在params中传参使用 ,这样只需要编译一次,下次使用调用缓存
这种类似于先注册UDF函数,使用 PUT 对 _scripts 传入脚本
在插入之后使用 GET 可以查看到对应的脚本内容
脚本中并没有指定params,params在调用的是有进行设置,调用的时候使用 id 指定my_script_1这个id即可,不再使用 source
所有update/update_by_query 脚本使用 ctx._source
除了上面快速开始的直接使用=赋值修改的情况,还可以对字段做数值运算,比如加减乘除开方等等
使用 Math.pow 对数值进行开方
Math下的方法还有 sqrt , log 等
主要说明下数组类型字段的更新,使用 ctx._source.字段.add/remove ,先新建一个带有数组字段的文档
使用script将tag数组字段增加元素,使用add
插入新元素后看下数据,已经成功
删除数组元素使用remove指定对应的索引位置即可
如果位数不足会报错类似数组越界
此功能使用search脚本,配合script中的 doc 实现,整体效果类似于map作,对所选定的文档作返回
先设置一个字段schema
插入一条日期数据
插入效果如下
下面检索所有文档,提取日期的年份,使用GET+_search请求,DSL中指定script_fields的自定义字段year,给year设置script脚本
doc.dt.value获取个数组元素,存储数据类型为 amic getter [org.elasticsearch.script.JodaComp ,该类型通过year属性获得年份。查看以下返回结果,由于没有筛选条件所有文档都被返回,存在dt字段的提取年份,不存在dt字段的也会有返回值为null, 由此可见_search + doc作实际上是完成了原始文档的一个映射转换作,并产生了一个自定义的临时字段,不会对原始索引做任何更改作
如果只返回存在dt字段的,需要在DSL中增加 query 逻辑
插入一个数值数组字段,搜索统计返回数组的和
插入数据
下面计算有goals字段的求goals的和到一个临时字段
在script中每一行结束要加 分号; ,使用Ja语法的循环求得数组的和,每个数组元素需要使用Ja语法中的Integer.parseInt解析,否则报错String类型无法转Num,查看返回
新建字段和删除字段都是update作,使用 ctx._source
对于存在dt字段的文档,新增一个字段dt_year,值为dt的年份
以上直接在source中使用ctx._source.dt_year引入一个新列,可惜直接报错
此处并没有向doc一样数据为日期类型而是字符串,因此需要引入Ja解析
查看结果
也可以做其他作比如获得LocalDateTime类型之后再做格式化输出
删除字段直接使用 ctx._source.remove("字段名") ,可以删除单个文档,也可以update_by_query批量删除
支持if,else if,else,比如根据某值进行二值判断生成新字段
return用在_search作中,配合script_fields使用,例如在搜索结果中新增一个字段area为china,此字段不更新到索引只是在搜索时返回
先插入3个子模型分,在生成一个总分,权重是0.6,0.2,0.2
现在计算总分给到score字段
看一下运行结果
直接取ctx._source对应字段进行比较,使用Ja三元表达式 ?: 赋值给新字段
有两种情况字段为null和params为null
如果某字段为空,文档不存在该字段,则填充为0
如果传入params不存在某个key,则删除该字段
在本例中使用 String[] cols = new String[3]; 创建了一个静态变量,对于这种类的变量painless的语法和Ja略有不同,写几个例子如下
List,Map这些都没有泛型,并且的值貌似不能直接初始化,需要add,put进来
查看某列的值大于某列,在query下可以使用script, 注意格式script下还套着一个script,search请求使用doc获取值
以上语句会报warn,doc选取字段如果字段为空会填充默认值,因此再限制一下字段不为空
Elasticsearch7.8.0 配置x-pack基础安全
X-Pack是Elastic Stack扩展功能,提供安全性,警报,监视,报告,机器学习和许多其他功能。 ES7.0+之后,默认情况下,当安装Elasticsearch时,会安装X-Pack,无需单独再安装。
自6.8以及7.1+版本之后,基础级安全免费。
默认情况下,拥有安全免费许可证时,Elasticsearch安全功能被禁用。 要启用安全功能,需要设置xpack.security.enabled。
在每个的elasticsearch.yml配置文件中,新增:
使用范围:配置传输层安全性适用于具有多个的集群以及需要外网通问的单ES。
使用环回地址127.0.0.1的单ES可以不用配置。
Elasticsearch可能存储是机密的数据,而无处不在的网络攻击对这些数据垂涎欲滴。
网络攻击包括对数据的嗅探,对数据的纵,以及试图获得对的访问权限,进而访问存储数据的文件。
保护的安全有助于降低来自网络的攻击的风险 。
1、证书实现加密通信的原理
TLS需要X.509证书(X.509 证书是一个数字证书,它使用 X.509 公有密钥基础设施标准将公有密钥与证书中包含的身份相关联。X.509 证书由一家名为证书颁发机构 (CA) 的可信实体颁发。CA 持有一个或多个名为 CA 证书的特殊证书,它使用这种证书来颁发 X.509 证书。只有证书颁发机构才有权访问 CA 证书)才能对与之通信的应用程序执行加密和身份验证。 为了使之间的通信真正安全, 必须对证书进行验证 。
在Elasticsearch集群中验证证书真实query 阶段知道了要取哪些数据,但是并没有取具体的数据,这就是 fetch 阶段要做的。性的方法是信任签署证书的证书颁发机构(CA)。
这样,只需要使用由同一CA签名的证书,即可自动允许该加入集群。
2、借助elasticsearch-certutil命令生成证书
启用安全功能后,必须使用TLS来确保之间的通信已加密。
在elasticsearch.yml中histogram(直方图)聚合,主要根据数值间隔分组,使用histogram聚合分桶统计结果,通常用在绘制条形图报表。心新增配置如下:
借助:elasticsearch-setup-passwords 设置集群密码。
核心:
interactive - 自定义不同用户的密码。
注意:必须配置好xpack之后,才能设置密码。否则会报错。
最简单的方法,
X-Pack安全配置的核心三步骤:
这些对于安全来说只是皮毛,更多的角色、权限、Space需要借助Kibana实现。
5.1 pom文件
5.2修改配置文件
kibana基础作
Kibana 是一款开源的数据分析和可视化平台,它是 Elastic Stack 成员之一,设计用于和 Elasticsearch 协作。可以使用 Kibana 对 Elasticsearch 索引中的数据进行搜索、查看、交互作。也可以很方便的利用图表、表格及地图对数据进行多元化的分析和呈现。
学习网址:
一、工具栏导航
graph
在Elasticsearch数据中显示并分析相关关系。
discover
通过查询和过滤原始文档以交互方式浏览数据。
visualize
dashboard
显示并共享可视化和保存的搜索的。
canvas
以像素完美的方式展示您的数据。
maps
探索来自Elasticsearch和Elastic Maps Serv的地理空间数据。
machine learning
自动对时间序列数据的正常行为建模以检测异常。
infrastructure
探索基础结构指标和常见,容器和服务的日志。
logs
实时流式记录日志或在类似控制台的体验中滚动浏览历史视图。
APM
从应用程序内部自动收集深入的性能指标和错误。
uptime
执行端点运行状况检查和正常运行时间监视。
SIEM
探索安全指标并记录和警报
Console
跳过cURL并使用此JSON接口直接处理您的数据。
Index Patterns
管理有助于从Elasticsearch检索数据的索引模式。
Monitoring
跟踪弹性堆栈的实时运行状况和性能。
Rollups
将历史数据汇总并存储在较小的索引中,以供将来分析。
Sa定是初始部署集群阶段。ved Objects
导入,导出和管理您保存的搜索,可视化和仪表板。
Security Settings
保护您的数据并轻松管理哪些用户可以访问用户和角色。
Spaces
Watcher
explain api 是 Elasticsearch 5.x 以后加入的非常实用的运维接口,可以用来诊断 shard 为什么没有分配,以及 shard 为什么分配在某个。通过创建,管理和监视警报来检测数据中的更改。
Dev Tools
开发工具
metrics
从上运行的作系统和服务收集指标。
mament
管理索引,索引模式,保存的对象,Kibana设置等。
二、查询语法
1.通配符搜索可以在单个条件下运行,?用于替换单个字符,以及替换零个或多个字符
2.常用表达通过将正则表达式模式包含在正斜杠("/")中,可以将它们嵌入查询字符串中
3.模糊性我们可以使用“模糊”运算符搜索与我们的搜索词相似但不完全相同的词
4.范围可以为日期,数字或字符串字段指定范围。包含范围用方括号指定,[min TO max]排除范围用花括号指定{min TO max}
三、Discover 的数据探索功能
搜索页面详情如下图:
四、Visualize的作及其配置
点击创建新的可视化,选择图表类型和数据索引来进行可视化绘图作。
可以通过单击 + Add Metrics 按钮来添加聚合。
为视图X轴选择一个桶聚合:
一旦指定了 X 轴聚合,可以定义子聚合来优化可视化。单击 + Add Sub Aggregation 定义子聚合,然后选择 Split Area 或 Split Chart ,然后从类型列表中选择一个子聚合。
在图表轴上定义多个聚合时,可以使用聚合类型右侧的向上或向下箭头来更改聚合的优先级。
五、Dashboard的使用
要用仪表板,你需要至少有一个已保存的 visualization。
Kibana 仪表板(Dashboard) 展示保存的可视化结果。在编辑模式下,可以根据需要安排和调整可视化结果集,并保存仪表板,以便重新加载和共享。
elasticsearch 首次查询缓慢 请问该如何优化
首次查询瓶颈在外部存储IO,思路是提升IO速度、减少IO{ "term": { "title": "hadoop" }},次数,可以:
使用SSD阵查询结果:列
更多shard
优化查询条件,比如按照时间范围检索,每个月一个index,query可以指定到对应的index
另一个思路,应用层优化:缓存预读
对于频繁查询的数据,后台程序在ES启动之后就进行查询,将数据加载到内存。前端发起的查询就不是首次查询了。
京东面试题:ElasticSearch深度分页解决方案
{"match": {Elasticsearch 是一个实时的分布式搜索与分析引擎,在使用过程中,有一些典型的使用场景,比如分页、遍历等。
在使用关系型数据库中,我们被告知要注意甚至被明确禁止使用深度分页,同理,在 Elasticsearch 中,也应该尽量避免使用深度分页。
这篇文章主要介绍 Elasticsearch 中分页相关内容!
在ES中,分页查询默认返回最顶端的10条匹配hits。
如果需要分页,需要使用from和size参数。
一个基本的ES查询语句是这样的:
上面的查询表示从搜索结果中取第100条开始的10条数据。
「那么,这个查询语句在ES集群内部是怎么执行的呢?」
在ES中,搜索一般包括两个阶段,query 和 fetch 阶段,可以简单的理解,query 阶段确定要取哪些doc,fetch 阶段取出具体的 doc。
如上图所示,描述了一次搜索请求的 query 阶段:·
在上面的例子中,coordinating node 拿到 (from + size) 6 条数据,然后合并并排序后选择前面的 from + size 条数据存到优先级队列,以便 fetch 阶段使用。
另外,各个分片返回给 coordinating node 的数据用于选出前 from + size 条数据,所以,只需要返回标记 doc 的 _id 以及用于排序的 _score 即可,这样也可以保证返回的数据量足够小。
coordinating node 计算好自己的优先级队列后,query 阶段结束,进入 fetch 阶段。
上图展示了 fetch 过程:
coordinating node 的优先级队列里有 from + size 个 _doc _id ,但是,在 fetch 阶段,并不需要取回所有数据,在上面的例子中,前100条数据是不需要取的,只需要取优先级队列里的第101到110条数据即可。
需要取的数据可能在不同分片,也可能在同一分片,coordinating node 使用 「multi-get」 来避免多次去同一分片取数据,从而提高性能。
「这种方式请求深度分页是有问题的:」
我们可以设在一个有 5 个主分片的索引中搜索。当我们请求结果的页(结果从 1 到 10 ),每一个分片产生前 10 的结果,并且返回给 协调 ,协调对 50 个结果排序得到全部结果的前 10 个。
现在设我们请求第 1000 页—结果从 10001 到 10010 。所有都以相同的方式工作除了每个分片不得不产生前10010个结果以外。然后协调对全部 50050 个结果排序丢弃掉这些结果中的 50040 个结果。
「对结果排序的成本随分页的深度成指数上升。」
「注意1:」
size的大小不能超过 index.max_result_window 这个参数的设置,默认为10000。
如果搜索size大于10000,需要设置 index.max_result_window 参数
「注意2:」
_doc 将在未来的版本移除,详见:
Elasticsearch 的From/Size方式提供了分页的功能,同时,也有相应的限制。
举个例子,一个索引,有10亿数据,分10个 shards,然后,一个搜索请求,from=1000000,size=100,这时候,会带来的性能问题:CPU,内存,IO,网络带宽。
在 query 阶段,每个shards需要返回 1000100 条数据给 coordinating node,而 coordinating node 需要接收 10 1000 ,100 条数据,即使每条数据只有 _doc _id 和 _score ,这数据量也很大了?
「在另一方面,我们意识到,这种深度分页的请求并不合理,因为我们是很少人为的看很后面的请求的,在很多的业务场景中,都直接限制分页,比如只能看前100页。」
比如,有1千万粉丝的微信大V,要给所有粉丝群发消息,或者给某省粉丝群发,这时候就需要取得所有符合条件的粉丝,而最容易想到的就是利用 from + size 来实现,不过,这个是不现实的,这时,可以采用 Elasticsearch 提供的其他方式来实现遍历。
深度分页问题大致可以分为两类:
「下面介绍几个提供的深度分页方法」
我们可以把scroll理解为关系型数据库里的cursor,因此,scroll并不适合用来做实时搜索,而更适合用于后台批处理任务,比如群发。
这个分页的用法, 「不是为了实时查询数据」 ,而是为了 「一次性查询大量的数据(甚至是全部的数据」 )。
因为这个scroll相当于维护了一份当前索引段的快照信息,这个快照信息是你执行这个scroll查询时的快照。在这个查询后的任何新索引进来的数据,都不会在这个快照中查询到。
但是它相对于from和size,不是查询所有数据然后剔除不要的部分,而是记录一个读取的位置,保证下一次快速继续读取。
不考虑排序的时候,可以结合 SearchType.SCAN 使用。
scroll可以分为初始化和遍历两部,初始化时将 「所有符合搜索条件的搜索结果缓存起来(注意,这里只是缓存的doc_id,而并不是真的缓存了所有的文档数据,取数据是在fetch阶段完成的)」 ,可以想象成快照。
在遍历时,从这个快照里取数据,也就是说,在初始化后,对索引插入、删除、更新数据都不会影响遍历结果。
「基本使用」
初始化指明 index 和 type,然后,加上参数 scroll,表示暂存搜索结果的时间,其它就像一个普通的search请求一样。
会返回一个 _scroll_id , _scroll_id 用来下次取数据用。
「遍历」
这里的 scroll_id 即 上一次遍历取回的 _scroll_id 或者是初始化返回的 _scroll_id ,同样的,需要带 scroll 参数。
重复这一步骤,直到返回的数据为空,即遍历完成。
「注意,每次都要传参数 scroll,刷新搜索结果的缓存时间」 。另外, 「不需要指定 index 和 type」 。
设置scroll的时候,需要使搜索结果缓存到下一次遍历完成, 「同时,也不能太长,毕竟空间有限。」
「优缺点」
缺点:
「优点:」
适用于非实时处理大量数据的情况,比如要进行数据迁移或者索引变更之类的。
ES提供了scroll scan方式进一步提高遍历性能,但是scroll scan不支持排序,因此scroll scan适合不需要排序的场景
「基本使用」
Scroll Scan 的遍历与普通 Scroll 一样,初始化存在一点别。
需要指明参数:
「Scroll Scan获取字段的方式除了使用 ctx._source.字段 之外,还可以 ctx._source['字段']与Scroll的区别」
如果你数据量很大,用Scroll遍历数据那确实是接受不了,现在Scroll接口可以并发来进行数据遍历了。
每个Scroll请求,可以分成多个Sl请求,可以理解为切片,各Sl并行,比用Scroll遍历要快很多倍。
上边的示例可以单独请求两块数据,最终五块数据合并的结果与直接scroll scan相同。
其中max是分块数,id是第几块。
Search_after 是 ES 5 新引入的一种分页查询机制,其原理几乎就是和scroll一样,因此代码也几乎是一样的。
「基本使用:」
步:
返回出的结果信息 :
上面的请求会为每一个文档返回一个包含sort排序值的数组。
这些sort排序值可以被用于 search_after 参数里以便抓取下一页的数据。
比如,我们可以使用的一个文档的sort排序值,将它传递给 search_after 参数:
若我们想接着上次读取的结果进行读取下一页数据,第二次查询在次查询时的语句基础上添加 search_after ,并指明从哪个数据后开始读取。
「基本原理」
es维护一个实时游标,它以上一次查询的一条记录为游标,方便对下一页的查询,它是一个无状态的查询,因此每次查询的都是的数据。
由于它采用记录作为游标,因此 「SearchAfter要求doc中至少有一条全局变量(每个文档具有一个值的字段应该用作排序规范)」
「优缺点」
「优点:」
「缺点:」
SEARCH_AFTER 不是自由跳转到任意页面的解决方案,而是并行滚动多个查询的解决方案。
分页方式性能优点缺点场景 from + size低灵活性好,实现简单深度分页问题数据量比较小,能容忍深度分页问题 scroll中解决了深度分页问题无法反应数据的实时性(快照版本)维护成本高,需要维护一个 scroll_id海量数据的导出需要查询海量结果集的数据 search_after高性能不存在深度分页问题能够反映数据的实时变更实现复杂,需要有一个全局的字段连续分页的实现会比较复杂,因为每一次查询都需要上次查询的结果,它不适用于大幅度跳页查询海量数据的分页
参照:
在 7. 版本中,ES不再使用Scroll方法来进行深分页,而是使用带PIT的 search_after 来进行查询;
从 7. 版本开始,您可以使用 SEARCH_AFTER 参数通过上一页中的一组排序值检索下一页命中。
使用 SEARCH_AFTER 需要多个具有相同查询和排序值的搜索请求。
如果这些请求之间发生刷新,则结果的顺序可能会更改,从而导致页面之间的结果不一致。
为防止出现这种情况,您可以创建一个时间点(PIT)来在搜索过程中保留当前索引状态。
在搜索请求中指定PIT:
分别分页获取 1 - 10 , 49000 - 49010 , 99000 - 99010 范围各10条数据(前提10w条),性能大致是这样:
对于向前翻页,ES中没有相应API,但是根据说法(
Scroll和 search_after 原理基本相同,他们都采用了游标的方式来进行深分页。
这种方式虽然能够一定程度上解决深分页问题。但是,它们并不是深分页问题的解决方案,深分页问题 「必须避免!!」 。
对于Scroll,无可避免的要维护 scroll_id 和 历史 快照,并且,还必须保证 scroll_id 的存活时间,这对是一个巨大的负荷。
对于 Search_After ,如果允许用户大幅度跳转页面,会导致短时间内频繁的搜索动作,这样的效率非常低下,这也会增加的负荷,同时,在查询过程中,索引的增删改会导致查询数据不一致或者排序变化,造成结果不准确。
Search_After 本身就是一种业务折中方案,它不允许指定跳转到页面,而只提供下一页的功能。
Scroll默认你会在后续将所有符合条件的数据都取出来,所以,它只是搜索到了所有的符合条件的 doc_id (这也是为什么用 doc_id 进行排序,因为本身缓存的就是 doc_id ,如果用其他字段排序会增加查询量),并将它们排序后保存在协调(coordinate node),但是并没有将所有数据进行fetch,而是每次scroll,读取size个文档,并返回此次读取的一个文档以及上下文状态,用以告知下一次需要从哪个shard的哪个文档之后开始读取。
这也是为什么不scroll用来给用户进行实时的分页查询,而是适合于大批量的拉取数据,因为它从设计上就不是为了实时读取数据而设计的。
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系 836084111@qq.com 删除。