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 还提供了通过模板搜索查询.我个人比较喜欢这种方式. 我们可以通过脚本预选 ...
随机推荐
- 阿里云ECS磁盘性能测试
阿里官方给出的性能指标 顺序读 测试命令 fio -directory=/var/lib/data -direct=1 -iodepth=1 -thread -ioengine=libaio -ran ...
- 学习java的第二十六天
一.今日收获 1.java完全学习手册第三章算法的3.2排序,比较了跟c语言排序上的不同 2.观看哔哩哔哩上的教学视频 二.今日问题 1.快速排序法的运行调试多次 2.哔哩哔哩教学视频的一些术语不太理 ...
- 我好像发现了一个Go的Bug?
从一次重构说起 这事儿还得从一次重构优化说起. 最近在重构一个路由功能,由于路由比较复杂,需求变化也多,于是想通过责任链模式来重构,刚好这段时间也在 Sentinel-Go 中看到相关源码. 用责任链 ...
- Qt5的安装和编译
Ubuntu18.04安装Qt5 1.配置unbuntu 和宿主机共享文件夹安装vmware-tools 2.下载 Qt http://download.qt.io/archive/qt/ 3.修改 ...
- KMP算法思路
题目 给定一个字符串\(S\),求\(M\)字符串是否是\(S\)字符串中的子串.如果是,返回\(M\)对应\(S\)的第一个下标,否则返回-1. 例如:S串为a b c d a b c d a b ...
- Learning Spark中文版--第三章--RDD编程(1)
本章介绍了Spark用于数据处理的核心抽象概念,具有弹性的分布式数据集(RDD).一个RDD仅仅是一个分布式的元素集合.在Spark中,所有工作都表示为创建新的RDDs.转换现有的RDD,或者调 ...
- 【Linux】【Web】【Nginx】配置nginx日志到远程syslog服务器
1. 概述: 主要是用于吧nginx的日志直接传送到远程日志收集的服务器上.远程日志服务器只要能够支持syslog协议都能够收到日志,本文的syslog服务器是IBM的日志收集系统Qradar. 2. ...
- Spring Boot项目的探究
一.pom.xml文件 1.父项目 <parent> <groupId>org.springframework.boot</groupId> <artifac ...
- CPU中的上下文
目录 一.简介 二.进程切换 三.线程切换 四.中断切换 五.中断检测和查看 六.模拟 一.简介 Linux是多任务操作系统,cpu划分固定时间片,分给每个进程,当前进程时间片执行完毕,将挂起,运行下 ...
- GIT最基本使用
带'*':必须操作 不带'*':可能需要而且经常用的 常见步骤为下: *1.克隆项目:有两种不同类型的网址(https/ssh) git clone [url] *2.初始化本地仓库 git init ...