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 还提供了通过模板搜索查询.我个人比较喜欢这种方式. 我们可以通过脚本预选 ...
随机推荐
- Freeswitch 安装爬坑记录1
2 Freeswitch的安装 2.1 准备工作 服务器安装CentOS 因为是内部环境,可以关闭一些防火墙设置,保证不会因为网络限制而不能连接 关闭防火墙 查看防火墙 systemctl statu ...
- oracle 根据ids转names
WITH t AS (SELECT '1,2,3,4' a, 1 b FROM Dual UNION ALL SELECT '1,2,3' a, 2 b FROM Dual),p AS ( ...
- 【Linux】【Basis】块存储,文件存储,对象存储
1. 块存储: 定义:这种接口通常以QEMU Driver或者Kernel Module的方式存在,这种接口需要实现Linux的Block Device的接口或者QEMU提供的Block Driver ...
- mysql explain using filesort
创建表,字段tid上无索引(mysql 5.7) CREATE TABLE `test` ( `tid` int(11) DEFAULT NULL, `tname` varchar(12) DEFAU ...
- What happens when more restrictive access is given to a derived class method in C++?
We have discussed a similar topic in Java here. Unlike Java, C++ allows to give more restrictive acc ...
- MySQL(1):SQLyog
数据库(DataBase,简称DB) 一. 基本数据库操作命令 flush privileges 刷新数据库 show databases 显示所有数据库 use dbname 打开某个数据库 sho ...
- navicat突然连接不上远程linux服务器上的mysql
我linux服务器上的mysql是docker安装的,突然有一天我的navicat连接不上服务器上的mysql,于是开始了下面一系列的修复 1.首先登录服务器上mysql,看是否能正常登录,我发现不能 ...
- 最小化安装centos ubuntu基础命令
# yum install vim iotop bc gcc gcc-c++ glibc glibc-devel pcre \ pcre-devel openssl openssl-devel zip ...
- List如何一边遍历,一边删除?
1.新手常犯的错误 可能很多新手(包括当年的我,哈哈)第一时间想到的写法是下面这样的: public static void main(String[] args) { List<String& ...
- 【Java多线程】线程池-ThreadPoolExecutor
ThreadPoolExecutor提供了四个构造方法: 我们以最后一个构造方法(参数最多的那个),对其参数进行解释: public ThreadPoolExecutor(int corePoolSi ...