《Elastic(中国)基础开发宝典》——Elasticsearch优化排序查询,更快获得结果

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: 《Elastic(中国)基础开发宝典》——Elasticsearch优化排序查询,更快获得结果

请求按某个字段对结果进行排序是Elasticsearch极为常用的操作。我们投入了大量 时间和精力来优化排序查询,以便为用户提供更快的排序查询体验。本篇博文将介 绍我们对数值和日期字段进行的一些排序优化。


1. 排序查询的工作原理


当您想要找到匹配筛选条件的文档,并请求按某个字段对结果进行排序时, Elasticsear-ch 会检查该字段的文档值找出所有匹配筛选条件的文档并根据排在 最前面的值选出前K个文档。最复杂的情况莫过于筛选条件极其宽泛(例如 match_all query),此时,我们必须检查并比较某个索引中所有文档的文档值。对 于大的索引来说,这一过程可能需要相当长的时间。


优化特定字段排序查询的方法之一是使用索引排序,并对该字段中的整个索引进行 排序。如果索引按字段进行了排序,那么其文档值也会被排序。因此,要获得按某 个字段排序的前K个文档,我们只需获取前K个文档,甚至不必检查其余的文档, 如此一来,排序查询自然就非常快了。

image.png

某字段的文档值(左)和按该字段排序的索引中该字段的相同文档值(右)

 

索引排序是一个不错的解决方案,但是您只能以单一方式进行索引排序。索引排序 并不适用于具有下列特征的排序查询:采用不同的排序标准,例如降序与升序;采 用不同的字段;或所用组合不同于索引排序定义中指定的组合。因此需要其他更灵 活的方法来提高排序查询的速度。


2. 使用 distance_feature 查询优化数值排序查询


以前,我们通过为每个文档块存储最大影响因素(词频与文档长度的组合)的方式, 显著提高了基于词且按score排序的查询的速度。在查询期间我们可以通过查看 文档块的最大影响因素来快速判断其是否具有竞争力。如果某个块不具有竞争力, 我们可以跳过整个文档块,这将极大地加快查询速度。


我们当时觉得有可能利用类似的方法来提高对数值或日期字段的排序查询速度。结 果证明,用distance_feature查询代替排序是可行的。distance_feature查询是种值得关注的查询方式,它会返回最接近给定原点的前K个文档。如果我们使用字 段的最小值作为原点,我们将得到按升序排序的前K个文档。使用最大值作为原点 则会按降序为我们提供前K个文档。


对我们来说distance_feature查询最具吸引力的特点在于,它可以有效跳过无竞 争力的文档块。为实现这一点,它需要依赖于BKD树的属性OBKD树在Elasticsearch 中用于索引数值和日期字段。类似于将文本字段的倒排索引划分为文档块的方法, BKD索引也被划分为单元格,并且每个单元格的最小值和最大值是已知的。因此, 只需检查单元格的最小值和最大值distance_feature查询就可以有效跳过文档无 竞争力的单元格。要运行这种排序优化方法,数值或日期字段既要有索引又要有文档值。


distance_feature查询代替对文档值进行排序使我们可以实现大幅提速(在某 些数据集上高达35倍增益)。我们已在Elasticsearch 76中引入了这种对日期和长 字段的排序优化。


3. 使用 search_after 优化排序查询


我们为所取得的这些提速成果感到欣慰不过在使用search_after参数进行排序的 问题上,我们还没有找到一个令人满意的解决方案。利用search_after进行排序十 分普遍,因为用户通常不仅会关注搜索结果的首页,也会对后续页面感兴趣。可以 确定的是,相较于当前使用的在Elasticsearch中重写排序查询的方法,更好的解决 方案是让Lucene中的比较器和收集器进行这种排序优化,并跳过无竞争力的文档。 Lucene中的比较器和收集器已支持search_after,得益于此,我们苦于寻找解决方 案的难题也迎刃而解了。我们将distance_feature查询用于跳过无竞争力文档块的 同一个Elasticsearch代码添加到Lucene的数值比较器中。


Elasticsearch716中,我们已利用search_after参数引入了这种排序优化。我们 发现,在一些夜间性能基准测试中,查询速度大幅提升(高达10倍)效果立竿见 影:

image.png

使用search_after 对具有多个段的索引进行排序优化(左)

强制合并到单个段的索引(右)

优化前2021-09-13),使用 search_after 的降序排序耗时 1400-1800ms 

优化后为200-300ms

 

4. 优化跨多个段的排序


个分片由多个段组成。Elasticsearch在搜索时会按顺序检查段,因此确定具有前 K个值的文档,先从最有可能包含此类文档的段开始处理会事半功倍。一旦收集了 具有前K个值的文档,我们就可以快速跳过仅含有排位靠后的值的其他段。


先从哪些段开始处理在很大程度上取决于用例。对于时间序列索引,最常见的请求 是对时间戳字段的结果进行降序排序,因为人们最关心的是查看最新事件。为了优 化时间序列索引的这种排序我们首先对@timestamp字段进行降序排序以便可 以最先处理包含最新数据的段,理想情况下,我们可以按时间戳文档在第一个段中 收集最新的数据并跳过所有其他段。这一方法强有力地提高了时间戳字段的降序排 序查询速度。


当较小的段合并成更大的段时,我们不希望出现最新的段排在最后,而其中最新的 文档也位列末尾的情况。为了更加均衡地合并段,我们引入了新旧段交叉的全新合 并策略,即新旧段的文档在全新的合并段中以混合顺序排列。这也可以让我们高效 查找最新的文档。


5. 优化跨多个分片的排序


Elasticsearch的强大之处在于它的分布式搜索,如果忽略了分布式的特点任何优 化都无法尽如人意。一些搜索可以跨越数百个分片(例如对时间序列索引的搜索) 对此,从"正确'‘的分片集和不包含具有竞争力命中结果的快捷分片集开始操作将 大有助益。该方法已得到全面落实。


Elasticsearch7.6开始,我们根据主排序字段的最大值/最小值对分片进行预排序以便我们可以从这样一个分片集开始分布式搜索,即其中的分片最有可能包含排在 最前面的值。从Elasticsearch7.7开始我们利用其他分片的结果实现快捷查询阶 段,即一旦我们从第一个分片集收集了排在最前面的值,就完全可以跳过其他分片, 因为相较于前面分片中计算得到的最后面的排序值,这些分片中所有候选的值还要 更加靠后。


在许多机器生成的时间序列索引中,文档遵循索引生命周期策略,从性能优化的硬 件开始,到成本优化的硬件结束,然后才是删除文档。这种分片跳过机制通常意味 着用户可以发送广泛的查询,并享受由其性能优化的硬件所定义的查询性能,因为 速度较慢和更经济的硬件上的分片会被跳过(使可搜索快照的应用更加高效)。


6. 对用户的影响


作为Elasticsearch的用户,您如何才能利用这些排序优化呢只有在无需跟踪某个 请求确切的总命中数且该请求不包含聚合时,这些排序优化才会发挥作用。如果您 需要知道确切的总命中数,我们就不能执行任何跳过操作,因为我们需要计算所有 匹配筛选条件的文档。


track_total_hits的默认值设置为10,000,也就是说,排序优化只有在收集了 10,000 个文档时才能开始。如果将此值设置为一个较小的数或“false",那么 Elasticsearch就可以更早地开始排序优化换言之,您的请求响应速度也会更快。


最近Kibana也开始在track_total_hits被禁用的情况下发送请求,因此Kibana中 的排序查询也应该会更快。

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
1月前
|
存储 自然语言处理 Java
Elasticsearch写入优化
【10月更文挑战第3天】Elasticsearch:从写入原理谈写入优化
70 2
|
3月前
|
SQL JSON 大数据
ElasticSearch的简单介绍与使用【进阶检索】 实时搜索 | 分布式搜索 | 全文搜索 | 大数据处理 | 搜索过滤 | 搜索排序
这篇文章是Elasticsearch的进阶使用指南,涵盖了Search API的两种检索方式、Query DSL的基本语法和多种查询示例,包括全文检索、短语匹配、多字段匹配、复合查询、结果过滤、聚合操作以及Mapping的概念和操作,还讨论了Elasticsearch 7.x和8.x版本中type概念的变更和数据迁移的方法。
ElasticSearch的简单介绍与使用【进阶检索】 实时搜索 | 分布式搜索 | 全文搜索 | 大数据处理 | 搜索过滤 | 搜索排序
|
30天前
|
存储 JSON 监控
大数据-167 ELK Elasticsearch 详细介绍 特点 分片 查询
大数据-167 ELK Elasticsearch 详细介绍 特点 分片 查询
48 4
|
28天前
|
开发框架 监控 搜索推荐
GoFly快速开发框架集成ZincSearch全文搜索引擎 - Elasticsearch轻量级替代为ZincSearch全文搜索引擎
本文介绍了在项目开发中使用ZincSearch作为全文搜索引擎的优势,包括其轻量级、易于安装和使用、资源占用低等特点,以及如何在GoFly快速开发框架中集成和使用ZincSearch,提供了详细的开发文档和实例代码,帮助开发者高效地实现搜索功能。
110 0
|
1月前
|
自然语言处理 搜索推荐 Java
SpringBoot 搜索引擎 海量数据 Elasticsearch-7 es上手指南 毫秒级查询 包括 版本选型、操作内容、结果截图(一)
SpringBoot 搜索引擎 海量数据 Elasticsearch-7 es上手指南 毫秒级查询 包括 版本选型、操作内容、结果截图
47 0
|
1月前
|
存储 自然语言处理 搜索推荐
SpringBoot 搜索引擎 海量数据 Elasticsearch-7 es上手指南 毫秒级查询 包括 版本选型、操作内容、结果截图(二)
SpringBoot 搜索引擎 海量数据 Elasticsearch-7 es上手指南 毫秒级查询 包括 版本选型、操作内容、结果截图(二)
32 0
|
2月前
|
JSON 自然语言处理 算法
ElasticSearch基础2——DSL查询文档,黑马旅游项目查询功能
DSL查询文档、RestClient查询文档、全文检索查询、精准查询、复合查询、地理坐标查询、分页、排序、高亮、黑马旅游案例
ElasticSearch基础2——DSL查询文档,黑马旅游项目查询功能
|
3月前
|
自然语言处理 Java 关系型数据库
ElasticSearch 实现分词全文检索 - 聚合查询 cardinality
ElasticSearch 实现分词全文检索 - 聚合查询 cardinality
97 1
|
3月前
|
存储 自然语言处理 Java
ElasticSearch 实现分词全文检索 - 经纬度定位商家距离查询
ElasticSearch 实现分词全文检索 - 经纬度定位商家距离查询
25 0
|
3月前
|
自然语言处理 Java
ElasticSearch 实现分词全文检索 - 高亮查询
ElasticSearch 实现分词全文检索 - 高亮查询
61 0

相关产品

  • 检索分析服务 Elasticsearch版