【Elasticsearch学习】文档搜索全过程
在ES执行分布式搜索时,分布式搜索操作需要分散到所有相关分片,若一个索引有3个主分片,每个主分片有一个副本分片,那么搜索请求会在这6个分片中随机选择3个分片,这3个分片有可能是主分片也可能是副本分片,然后收集所有分片的查询结果。所以ES的搜索过程分为两个阶段,Query阶段和Fetch阶段;ES有两种搜索类型:query_then_fetch,dfs_query_then_fetch。
1.Query阶段
1)转发请求。在Query阶段客户端向ES节点发送,搜索请求,Coordinate节点接受客户端搜索请求,Coordinate节点负责解析搜索请求,并在索引的所有主副本分片中随机选择分片,并且发送给分片所在的数据节点。
2)执行查询。接收到查询请求的数据节点执行查询操作,并对查询结果进行排序,每个节点都会根据请求中参数返回from+size个排序后的文档Id和排序值给Coordinate节点。
2.Fetch阶段
1)重排序。Coordinate节点收到数据节点返回的数据后,会按照返回的排序值对从所有分片取回的值重新进行排序,最终只选取客户端需要的from+size个文档的Id。
2)获取文档数据。Coordinate节点根据选取的文档的Id,到相应的分片获取详细的文档数据,最终将查询到的结果返回给客户端。
查询结果解读:
{
"took":3, 查询所用的毫秒数
"timed_out":false, 是否有分片超时,即是否只返回了部分结果
"_shards":{
"total":1, 一共查询了多少分片
"successful":1, 多少分片成功返回
"skipped":0,跳过了多少分片
"failed":0 多少分片查询失败
},
"hits":{
"total":{
"value":1, 该搜索请求中返回的所有匹配的数量
"relation":"eq" 文档与搜索值的关系,eq表示相等
},
"max_score":8.044733, 返回结果中文档的最大得分
"hits":[ 查询结果的文档数组
{
"_index":"kibana_sample_data_ecommerce", 查询的索引
"_type":"_doc", 查询的类型
"_id":"4X-j7XEB-r_IFm6PISqV", 返回文档的主键
"_score":8.044733, 返回文档的评分
"_source":{ 文档的原始内容
"currency":"EUR",
"customer_first_name":"Eddie",
"customer_full_name":"Eddie Underwood",
"customer_gender":"MALE"
......
}
}
]
}
}
Query Then Fetch潜在的问题
1.深度分页
ES索引数据分布在多个分片上,在查询时,每个分片都要查询from+size个文档,Coordinate节点会聚合所有的结果,所以Coordinate节点要处理查询分片数*(from+size)个文档记录,对这些记录进行重新排序,需要的size个文档,from+size的值越大占用内存越多,称为深度分页问题,ES默认限制分页的深度不能超过10000条,可通过max_result_window设置。
深度分页解决办法:
1)Search After
可以使用Search After避免深度分页的性能问题,实时获取下一页的文档信息,search_after根据上一页最后一个文档的sort值来查询下一页,并且当索引数据有变化时,也可以同步被查到,是一个实时查询的方法。
例:http://127.0.0.1:9200/kibana_sample_data_ecommerce/_search
查询参数:在使用Search_After查询时,第一步查询时需要指定sort字段,并且该sort字段的排序结果是唯一的,建议使用_id来进行sort,可以指定多个sort字段。
{
"size": 1,
"query": {
"match": {
"currency": "EUR"
}
},
"sort": [
{
"order_id": {
"order": "asc"
}
}
]
}
返回中可以看到第一页查询返回的sort值,查询下一页时使用该sort值进行文档的定位,而后每个查询都会返回一个sort值,供下一页进行定位使用。
"sort": [
"550375"
]
下一页查询:
{
"size": 1,
"query": {
"match": {
"currency": "EUR"
}
},
"search_after": [
550375
],
"sort": [
{
"order_id": {
"order": "asc"
}
}
]
}
Search_After存在的限制:
a.不能指定from值,即不能想翻到哪一页就直接跳转到那一页,只能一页一页按照顺序翻;
b.只能往后翻页,不能往前翻页。
2)Scroll API
scroll api可以用于从单个搜索请求中检索大量的结果,其原理是建立索引在某个时间点的快照,当快照建立后,之后的每次搜索都会在该快照上进行,对索引的所有新增操作都会被忽略,索引Scroll适合于处理大量数据,但是不能保证数据的实时性。
POST http://127.0.0.1:9200/kibana_sample_data_ecommerce/_search?scroll=1m
首次查询时指定scroll=5m,表示当前搜索过期时间为5分钟,即查询结果在搜到下一次请求之前会保存多次时间,scroll的值不需要长到把整个快照的数据都处理完,只需保证下一次搜索请求到来之前能处理完前一批查询结果即可。
{
"size": 2,
"query": {
"match" : {
"currency" : "EUR"
}
}
}
返回中可以看到_scroll_id,total.value,scroll_id用于获取下一批的查询结果,total.value表示该查询有总共多少个结果。
{
"_scroll_id":"DXF1ZXJ5QW5kRmV0Y2gBAAAAAAABAGUWdks0dUtFMHZTYmE1Rl9ucGp5X0hoUQ==",
"took": 1,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 4675,
"relation": "eq"
},
}
}
下一页:
http://127.0.0.1:9200/_search/scroll
下一页查询的时候不用指定索引和查询参数,只需要指定scroll时间和上一次请求返回的scroll_id,因为快照已经建好,只需要在快照上往下翻页即可。每次执行该请求都会往下进行翻页,直到查询的结果为空。
{
"scroll":"5m",
"scroll_id":"DXF1ZXJ5QW5kRmV0Y2gBAAAAAAABAGUWdks0dUtFMHZTYmE1Rl9ucGp5X0hoUQ=="
}
Scroll API存在的限制:当快照建立后,对索引有新的操作时,无法被查询到,所以不适合做实时查询。
不同查询的使用场景
一般查询:需要获取顶部的部分文档,查询索引最新的数据。
全量查询:使用scroll,当需要导出全部数据,且对数据的实时性要求不高时。
分页查询:使用from+size,当from+size过大时,使用search after。
2.相关度评分不准问题
当搜索请求在多个shard进行数据查找时,每个分片都会基于自己分片上的文档数据进行相关度的计算,计算方法为TD/IDF,
TF:词频,表示词条在一个文档中出现的频率;IDF:逆文档频率,log(全本文档数/词条在所有文档中出现的次数),表示该term在所有文档中出现的频率;如果查询词条在某一个文档中出现的频率(即TF)高,在全部文档中出现的频率低(即IDF)低,则表明该文档的相关性高。
每个分片计算IDF的时候只会基于自己分片上的数据进行计算,并不会包含其他分片上的数据,所以这样会导致相关性评分不准的情况;特别在文档总数很少情况下,主分片数越多,相关性算分会越不准。
解决相关度评分不准问题的方法:
1)合理设置分片数量,保证数据均匀分布。
当数据量不大时,可以考虑仅设置一个主分数;当数据量较大时,保证文档均匀的分布在各个分片上。ES提供了
routing_partition_size越大,数据的分布越均匀(【Elasticsearch学习】之一图读懂文档索引全过程 中有提及)。routing_partition_size参数,
2)使用dfs_query_then_fetch
在搜索时,指定搜索的类型search_type=dfs_query_the_fetch,在搜索的时候,每个分片会把每个分片的TF和IDF进行搜集,然后综合所有的数据进行一次完整的相关性评分计算,但是一般不推荐,因为这样会耗费较多的CPU和内存。
【Elasticsearch学习】文档搜索全过程的更多相关文章
- ElasticSearch学习文档2018.11
1 Elasticsearch安装 1.1 ES6.0版本安装head插件 1.1 下载head插件 下载地址:https://github.com/mobz/elasticsear ...
- ElasticSearch(2)-文档
上一篇 ES(1) 官网原地址:https://www.elastic.co/guide/en/elasticsearch/reference/1.7/_cluster_health.html ES权 ...
- elasticsearch 路由文档到分片
路由文档到分片 当你索引一个文档,它被存储在单独一个主分片上.Elasticsearch是如何知道文档属于哪个分片的呢?当你创建一个新文档,它是如何知道是应该存储在分片1还是分片2上的呢? 进程不能是 ...
- Ext JS 6学习文档-第5章-表格组件(grid)
Ext JS 6学习文档-第5章-表格组件(grid) 使用 Grid 本章将探索 Ext JS 的高级组件 grid .还将使用它帮助读者建立一个功能齐全的公司目录.本章介绍下列几点主题: 基本的 ...
- ElasticSearch——原始文档和倒排索引
一.原始文档 如上图所示, 第二象限是一份原始文档,有title和content2个字段,字段取值分别为”我是中国人”和” 热爱共X产党”,这一点没什么可解释的.我们把原始文档写入Elasticsea ...
- 007-elasticsearch5.4.3【一】概述、Elasticsearch 访问方式、Elasticsearch 面向文档、常用概念
一.概述 Elasticsearch 是一个开源的搜索引擎,建立在一个全文搜索引擎库 Apache Lucene™ 基础之上. Elasticsearch 也是使用 Java 编写的,它的内部使用 L ...
- Elasticsearch 删除文档
章节 Elasticsearch 基本概念 Elasticsearch 安装 Elasticsearch 使用集群 Elasticsearch 健康检查 Elasticsearch 列出索引 Elas ...
- Elasticsearch 更新文档
章节 Elasticsearch 基本概念 Elasticsearch 安装 Elasticsearch 使用集群 Elasticsearch 健康检查 Elasticsearch 列出索引 Elas ...
- .Net Api 之如何使用Elasticsearch存储文档
.Net Api 之如何使用Elasticsearch存储文档 什么是Elasticsearch? Elasticsearch 是一个分布式.高扩展.高实时的搜索与数据分析引擎.它能很方便的使大量数据 ...
随机推荐
- Linux下配置mail使用外部SMTP发送邮件
修改/etc/mail.rc,增加两行:指定外部的smtp服务器地址.帐号密码等. # vi /etc/mail.rc set from=demo@qq.com smtp=smtp.qq.com se ...
- 高德APP启动耗时剖析与优化实践(iOS篇)
前言最近高德地图APP完成了一次启动优化专项,超预期将双端启动的耗时都降低了65%以上,iOS在iPhone7上速度达到了400毫秒以内.就像产品们用后说的,快到不习惯.算一下每天为用户省下的时间,还 ...
- STL迭代器的使用
STL的迭代器听起来怪吓人的,其实并不是什么高深的东西,说白了就是定义了一个指向STL的指针.. 对于没个STIL都可以定义 set,,vector ,,map,,,string 定义: set< ...
- C++ 11 +,开坑。
最近换新工作了.工作中需要用到高端的c++11的一些操作,至于我后面又plus一下还是因为可能是c++14或者17中提供的一些操作.反正都是c++11以及之后的一些特性. 首先,今天看一下关于函数模板 ...
- Linux命令与Shell
Linux 目录结构及解释 查看命令行执行完位置: echo $BASH 命令记录 mkdir mkdir命令 用来创建目录. 语法:mkdir (选项)(参数) 主要选项: -m<目标属性& ...
- NCTF2018_easy_audit->coding_breaks
easy_audit 题目源码 <?php highlight_file(__FILE__); error_reporting(0); if($_REQUEST){ foreach ($_REQ ...
- 解析网站爬取腾讯vip视频
今天用油猴脚本vip一件解析看神奇队长.想到了问题,这个页面应该是找到了视频的api的接口,通过接口调用获取到了视频的地址. 那自己找腾讯视频地址多费劲啊,现在越来越多的参数,眼花缭乱的. 那我就找到 ...
- 2020.4面试分享(7面收割5个offer)
都说金三银四是找工作的最佳时节,由于本人的个人职业规划跟目前工作内容不太相符(具体原因就不透露了,领导平时也要来这里逛,哈哈),四月份挑选了10多家公司投递简历(公司规模从几十人到上万人都有),参加了 ...
- [源码分析] 带你梳理 Flink SQL / Table API内部执行流程
[源码分析] 带你梳理 Flink SQL / Table API内部执行流程 目录 [源码分析] 带你梳理 Flink SQL / Table API内部执行流程 0x00 摘要 0x01 Apac ...
- 解决报错:JPA-style positional param was not an integral ordinal;
org.hibernate.QueryException: JPA-style positional param was not an integral ordinal; nested excepti ...