Elasticsearch核心技术(五):搜索API和搜索运行机制
本文将从数据存储和搜索的角度简单分析Elasticsearch的搜索运行机制,主要涉及搜索API、搜索机制、存在问题和解决方案。
4.1 Search API
Search API允许用户执行一个搜索查询并返回匹配查询的搜索命中结果。
Elasticsearch查询主要有两种方式:URI Search和Request Body Search。
URI Search:通过URI参数实现搜索,特点是操作简便,仅包含部分查询语法,常用参数如下:
q:指定查询语句,使用Query String Syntax
df:默认字段,不指定时,会对所有字段进行查询
sort:排序
profile:用于查看查询是如何被执行的Request Body Search:完备的查询语法Query DSL,所以还是建议使用Request Body Search。
4.2 深入了解Search运行机制
建议先参考上篇Elasticsearch核心技术(四):索引原理分析,其中主要介绍了ES的分布式存储架构和原理。
4.2.1 Query-then-Fetch运行机制
Elasticsearch的分布式搜索的运行机制称为Query-then-Fetch。具体分为Query和Fetch两个阶段:

Query阶段
用户发出搜索请求到达ES节点。节点收到请求后,会以协调节点(Coordinating Node)的身份,在6个主副分片中随机选择3个分片,发送查询请求。
被选中的节点,进行排序(根据score值进行排序)。然后每个分片都返回 From+size 个排序后的文档id和排序值给协调节点。 注意这里返回的是文档id。
Fetch阶段
Coordinating节点将Query阶段从每个分片获取的排序的文档id列表重新进行排序,选取 From 到 From+size 个文档的id。
以multi get请求的方式,到相应的分片获取详细的文档数据。
4.2.2 为什么需要两阶段才能完成搜索
因为Elasticsearch在查询的时候不知道文档位于哪个分片,因此索引的所有分片都要参与搜索,然后协调节点将结果合并,在根据文档ID获取文档内容。例如现在有5个分片,需要查询匹配度Top10的数据,那么每个分片都要查询出当前分片的Top10的数据,协调节点将5×10个结果再次进行排序,返回Top10的结果给客户端。
4.2.3 Query-then-Fetch存在问题和解决方案
Query-then-Fetch存在问题分为两方面,一个是性能问题,一个是相关性算分问题。
- 性能问题
性能问题主要表现为深度分页的问题。Elasticsearch数据是分片存储的,数据分布在多台机器上。有这样一个场景,如何获取前1000个文档?当获取从990-1000的文档时候,会在每个分片上面都先获取1000个文档,然后再由协调节点聚合所有分片的结果在排序选取前1000个文档。
这个过程有什么问题吗?当然是有的,页数越深,处理文档越多,占用内存越多,耗时越长。所以要尽量避免深度分页。当然,ES官方也注意了这个问题,所以通过index.max_result_window限定最多到10000条数据。当然我们也可以根据业务需要修改这个参数,这也解释了:为什么Google搜索结果只有相关度最高的17页结果,百度只有76页的结果,原因之一是受限于Elasticsearch深度分页的性能问题。


相关性算分问题
另外一个问题是相关性算分不准确问题。每个分片都基于自己分片上面的数据进行相关度计算。这会导致打分偏离的情况,特别是数据量很少的时候。相关性算分在分片之间是相互独立。当文档总数很少的情况下,如果主分片大于1,如果主分片数越多,相关性算分会越不准。如何解决算分不准的问题?
- 当数据量不大的时候,将主分片数设置为1;当数据量足够大的时候,只要保证文档均匀分布在各个分片上面,结果一般不会出现偏差
- 使用
DFS Query Then Fetch
在搜索的URL中指定参数_search?search_type=dfs_query_then_fetch;这样就可以保证每个分片把各个分片的词频和文档频率进行搜集,然后进行一次相关性算分。但是这样会耗费更多的CPU和内存资源,执行性能较低。
- 如何避免深度分页的问题?
使用Search_After:
ES提供实时的下一页文档获取功能,这个功能只能下一页,不能上一页;
不能指定页数,不能使用from参数;
- 三种分页方式对比:
| 类型 | 场景 |
|---|---|
| From/Size | 需要实时获取顶部的部分文档,且需要自由翻页 |
| Scroll | 需要全部文档,如导出所有数据的功能 |
| Search_After | 需要全部文档,不需要自由翻页 |
4.3 总结
经济基础决定上层建筑,ES的分片存储决定了搜索机制。其实存储和搜索不能分割开来看,只存储不可搜索,这个存储是没有意义的;只搜索没有存储(数据源)是空中楼阁。
Elasticsearch核心技术(五):搜索API和搜索运行机制的更多相关文章
- ElasticSearch(十五) _search api 分页搜索及deep paging性能问题
1.分页搜索 语法: size,from GET /_search?size=10 GET /_search?size=10&from=0 GET /_search?size=10&f ...
- 五:理解控件的运行机制(例:基于Control命名空间的简单控件)
一:先用最简短的话说点理论的1.asp.net中所有的标准控件都可以重写 2.和控件相关的命名空间有 System.Web.UI.Control是所有控件的基类只提供简单的呈现逻辑,不支持样式表 Sy ...
- elasticsearch系列四:搜索详解(搜索API、Query DSL)
一.搜索API 1. 搜索API 端点地址 从索引tweet里面搜索字段user为kimchy的记录 GET /twitter/_search?q=user:kimchy 从索引tweet,user里 ...
- Golang 谷歌搜索api 实现搜索引擎(前端 bootstrap + jquery)
Golang 谷歌搜索api 实现搜索引擎(前端 bootstrap + jquery) 体验 冒号搜索 1. 获取谷歌搜索api 谷歌搜索api教程 2. 后台调用 程序入口 main.go // ...
- ES系列五、ES6.3常用api之搜索类api
1.搜索api 1.1.routing:路由 执行搜索时,它将广播到所有索引/索引分片(副本之间的循环).可以通过提供routing参数来控制将搜索哪些分片.例如,在索引book时,路由值可以是nam ...
- ElasticSearch查询 第一篇:搜索API
<ElasticSearch查询>目录导航: ElasticSearch查询 第一篇:搜索API ElasticSearch查询 第二篇:文档更新 ElasticSearch查询 第三篇: ...
- SpringBoot:elasticSearch 7.2.0 Java High Level REST Client 搜索 API
Springboot整合最新版elasticSearch参考之前的文章:SpingBoot:整合ElasticSearch 7.2.0 Search API SearchRequest用于与搜索文档, ...
- Elasticsearch java api 基本搜索部分详解
文档是结合几个博客整理出来的,内容大部分为转载内容.在使用过程中,对一些疑问点进行了整理与解析. Elasticsearch java api 基本搜索部分详解 ElasticSearch 常用的查询 ...
- ElasticSearch High Level REST API【5】使用模板搜索
ElasticSearch Rest高级API 提供了多种搜索方式,除了前面讲到的search查询,ElasticSearch 还提供了通过模板搜索查询.我个人比较喜欢这种方式. 我们可以通过脚本预选 ...
随机推荐
- 大数据学习day18----第三阶段spark01--------0.前言(分布式运算框架的核心思想,MR与Spark的比较,spark可以怎么运行,spark提交到spark集群的方式)1. spark(standalone模式)的安装 2. Spark各个角色的功能 3.SparkShell的使用,spark编程入门(wordcount案例)
0.前言 0.1 分布式运算框架的核心思想(此处以MR运行在yarn上为例) 提交job时,resourcemanager(图中写成了master)会根据数据的量以及工作的复杂度,解析工作量,从而 ...
- 设计和实现OLAP解决方案 [转]
第一讲 简介首先,啥叫数据仓库? 数据仓库就是数据的仓库!用外文说叫Data Warehouse,简称DW. 是不是哐当倒下一片啊,要不咱换个专业点的说法? 数据仓库是一个面向主题的.集成的.相对稳定 ...
- 容器之分类与各种测试(三)——slist的用法
slist和forward_list的不同之处在于其所在的库 使用slist需要包含 #include<ext\list> 而使用forward_list则需要包含 #include< ...
- mystar01 nodejs MVC 公共CSS,JS设置
mystar01 nodejs MVC gulp 项目搭建 config/express.js中定义别名 //将下载的第三方库添加到静态资源路径当中,方便访问 app.use('/jquery', e ...
- Swift3.0 延时执行
//延时1s执行 DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Double(Int64(1*NSEC_PER_SEC))/ ...
- vue中vuex的五个属性和基本用法
VueX 是一个专门为 Vue.js 应用设计的状态管理构架,统一管理和维护各个vue组件的可变化状态(你可以理解成 vue 组件里的某些 data ). Vuex有五个核心概念: state, ge ...
- Servlet(3):Cookie和Session
一. Cookie Cookie是客户端技术,程序把每个用户的数据以cookie的形式写给用户各自的浏览器.当用户使用浏览器再去访问服务器中的web资源时,就会带着各自的数据去.这样,web资源处理的 ...
- springboot+vue脚手架使用nginx前后端分离
1.vue配置 /** * * 相对于该配置的nginx服务器请参考nginx配置文件 * */ module.exports = { // 基本路径 publicPath: '/', // 输出文件 ...
- 【Java 8】Stream.distinct() 列表去重示例
在这篇文章里,我们将提供Java8 Stream distinct()示例. distinct()返回由该流的不同元素组成的流.distinct()是Stream接口的方法. distinct()使用 ...
- 【Linux】【CentOS】【FTP】FTP服务器安装与配置(vsftpd、lftp)
[初次学习.配置的笔记,如有不当,欢迎在评论区纠正 -- 萌狼蓝天 @ 2021-12-02] 基本概念 FTP访问方式 实体账号:本地账户 来宾账户:guest 匿名登录:anonymous fp ...