一道之前的面试题:
来自:社招一年半面经分享(含阿里美团头条京东滴滴)
文章首发在公众号(月伴飞鱼),之后同步到个人网站:xiaoflyfish.cn/
微信搜索:月伴飞鱼,交个朋友,进面试交流群
- 公众号后台回复666,可以获得免费电子书籍
觉得不错,希望缓存英文点赞,在看,转发支持一下,谢谢
前言
ElasticseGitHubarch 是一个实时的GitHub分布式搜索与分析引擎,在使用过程中,有一些典型的使优先级调度算法用场景,比如优先级是什么意思分页、遍历等。
在使用关系型数据库中,我们被告知要注意甚至被明确禁止使用深度分页,缓存是什么意思同理,在 Elasticsearch 中,也应该尽量避免使用深度分页。
这篇文章主要介绍 Elasticsearch 中分页相关内容!
From/Size参数
在ES中,分页查询默认返回最顶端的10条匹配hits。
如果需要分github直播平台永久回家页,需要使用from和size参数。
- from参数定义了需要跳github中文官网网页过的hits数,默认为0;
- size参数定义了需要返回的hits数目的最大值。
一个基本的ES查询语句是这样的:
POST /my_index/my_type/_search
{
"query": { "match_all": {}},
"from": 100,
"size": 10
}
上面的查询表示从搜索结果中取第100条开始的10条数据。
「那么,这个查询语句在ES集群内部是怎么执行的呢?」
在ES中,搜索一github下载般包括两个阶段,query 和 fetch 阶段,可以简单的理解,query 阶段确服务器内存条可以用在台式机上吗定要取哪些doc,fetch 阶段取出具体的 doc。
❝
Query阶段
❞
如上图所示优先级英文,描述了一次搜索请求服务器租用的 query 阶段:
- Client 发送一次搜索请求,node1 接收到请求,然后,node1 创建一个大小为
from + size
的优先级队列用来存结果,我们管 no面试问题de1 叫 coordinating no优先级c语言de。缓存视频合并app - coordinating node将请求广播到涉及到的 shards,每个 shard 在内部执行搜索请求,然后,将结果存到内部的大小同样为
from + size
的优先级队列里,可以把优先级队列理解为一个包含top N
结果的列表。 - 每个 shard 把github中文官网网页暂存在自身优先级队列里的数据返回给 coordinating node,coordinating node 拿到各个 shards 返回的结果后对结果进行一github直播平台永久回家次合并,产生一个全局的优先级队列,存到自身的优先级队列里。
在上面的例子中,coordinating node 拿到(from + size) * 6
条数据,然后合并并排序后选择前面的from + size
条数据存到优先级队列,以便 fetch 阶服务器租用多少钱一年段使用。
另外,缓存各个分片返回给 coordinating node 的数据用于选出前from + size
条数据,所以,只需要返回唯一标记 doc 的_id
以及优先级最高的运算符用于排序的_score
即可,这样也优先级英文可以保证返回的数据量足够小。
coordinating nod服务器系统e 计算好自己的服务器怎么搭建优先级队列后,query 阶段结束,进入 fetch 阶段。
❝
Fetch阶段
❞
query 阶段知道了要取哪些数据,但是并没有取具体的数据,这就是 fetch 阶优先级越小越优先吗段要做的。
上图展示了 fetch 过程:
- coordinating node 发送 GET 请求到相关shar缓存清理ds。缓存视频合并
- shard 根据 d优先级oc 的
_id
取到数据详情,然后返回给 coordinating node。 - coordinating node 返回数据给 Client。
coordinating node 的优先级队列里有from + size
个_doc _id
,但是,在 fetch 阶面试段,并服务器是什么不需要缓存取回所有数据,在上面的例子中,前100条数据是不需要取的,只需要取优先级队列里的第101到110条数据即可。
需优先级c语言要取的数据可能在不同分片,也可能在同一分片,coordi面试自我介绍简单大方nating node 使用 「mul优先级排序ti-get」 来避免面试技巧和话术大全多次去同一分片取数据,从而提高性能。
「这种方式请求深度分页是有问题的:」
我们可以假设在一个有 5 个主分片的索引中优先级调度算法搜索。当我们请求结果的第一页(结果从 1 到 10 ),每一个分片产生前 10 的结果,并且返回给 协调缓存视频合并节点 ,优先级表协调节点对 50 个结果排序得到全部结果的前 10 个。
现在假设我们请求第 1000 页—结果从 10001 到 10010 。所有都以相同的方式工作除了每个分片不得不产生前10010个优先级结果以外。然后协调节点对全部 50050 个结果排序最后丢弃掉这些结果中的 50040 个结果。
「对结果排序的成本随分页的深度成指数上升。」
「注意1:」
size的大小不能超过index.ma服务器地址x_result_window
这个参数的设置,默认为10000。
如果搜索size大于10000,服务器内存条可以用在台式机上吗需要设置index.max_re面试技巧和注意事项sult_window
参数
PUT _settings
{
"index": {
"max_result_window": "10000000"
}
}
「注优先级表意2:」
_doc
将在未来的版本移除,详见:
- www.elastic.co/cn/blog/mov…
- elasticsearch.cgithub永久回家地址n/arti优先级最高的运算符cle/158
深度分页问题
Elasticsearch 的From/Size方式提供了分页的功能,同时,也有相应的限制。
举个例子,一个索引,有10亿数据,分10个 shards,然后,一个搜索请求,from=1000000,size=100,这时候,会带来严重的性能问题:CPU,内存,IO,网络带宽。
在 query 阶段,每个shards需要返回 1000100 条数据给 coordinating node,而 coordinating node 需要接收10 * 1000
,100 条数据,即使每条数据只有 _doc _id
和 _score
,这数据量也很大了?
「在另一方面,我们意识到,这种深度分页的请求并不优先级越小越优先吗合理,因为我们是很少人为的看很后面的请求的,在很多的业务场景中,都直接限制分页,比如只能看前1缓存的视频在哪00页。」
比如,有1千万粉面试自我介绍3分钟通用丝的微信大V,要给所有粉丝群服务器租用发消息,或者给某省优先级英文粉丝群发,这时候就需要取得所有符合条件的粉丝,而最容易想到的就是利用 from + size 来实现,不过,这GitHub个是不现实的,这时,可以采用 Elast服务器租用多少钱一年icsearch 提供的其他方式来实现遍历。
深度分页问题大致可以分为两优先级队列类:
- 「随机深度分页:随机跳转页面」
- 「滚动深度分页:只能一页一页往下查询」
「下面介绍几个官方提供的深度分页方法」
Scroll
❝
Scroll遍历数据
❞
我们可以把scroll理解为关系型数缓存英文据库里优先级排序c语言的curso缓存视频在手机哪里找r,因此,scroll并不适合用来做实时搜索,而更适合用于后台批处理任务,比如群发。
这个分页的用法,「不是为了实时查询数据」,而是为了**「一次性查询大量的数据(甚至是全github开放私库部的数据」**)。
因为这个scroll相当于维护了一份当前索引段的快照信息,这个快照信息是你执行这个scroll查询时的快照。在这个查询后的任何新索引进来的数据github下载,都不会在这个快照中查询到。
但是它相对于from和size,不是服务器查询所有数据然后剔除不要的部分,而是记录一个读取的位置,github中文官网网页保证下一次快速github开放私库继续读取。
不考面试常见问题及回答技巧虑排序的时候,可以结合SearchType.SCAN
使用。
scroll可以分为初始化和遍历两部,初始化时将**「所有符合搜索条件的搜索结果缓存起来(注意,这里只是缓存的doc_id缓存文件夹名称,而并不是真的缓存了所有的文档数据,取数据是在fetch阶段完成的)」**,可以想象成快照。
在遍历时,从这个快github开放私库照里取数据,也就是说,在初始化后,对索引插入、删除、更新数据都不会优先级影响遍历结果。
「基本使用」
POST /twitter/tweet/_search?scroll=1m
{
"size": 100,
"query": {
"match" : {
"title" : "elasticsearch"
}
}
}
初始化指明 index 和 type,然后,加上参数 scroll,表示暂存搜索结果的时间,其它就像一个普通的search请求一样。
会返回优先级c语言一个_scroll_id
,_scroll_id
用来下次取数据用。
「遍历」
POST /_search?scroll=1m
{
"scroll_id":"XXXXXXXXXXXXXXXXXXXXXXX I am scroll id XXXXXXXXXXXXXXX"
}
这里的scroll_id优先级
即 上一次面试技巧和注意事项遍历取回的_scroll_id
或者是初始化返回的_scro优先级排序c语言ll_id
,同样的,需要带 scroll 参数。
重复这一步骤,直到返回的数据为空,即遍历完面试自我介绍简单大方成。
「注意,每次都要传参数 scroll,刷新搜索结果的缓存时间」。另外,「不需要指定 index 和 type」。
设置scroll的时候,需要使搜索结果缓存到下一次遍历完成,「同时,也不能太长,毕竟空间有限。」
「优缺点」
缺点:
- 「scroll_id会占用大量的资源(特别是排序的请求)」
- 同样的,scroll后接超时时间,频繁的发起scroll请求,会出现一些列问题。
- 「是生成的历史快优先级照,对于数据的变更不会反映到快照上。」
「优点:」
适用于非实时处理大量数据的情况,比如要进行数据迁移或者索引变更之类的。
Scroll Scan
ES提供了scroll scan方式进一步提高遍历性能,但是scroll scan不支持排序,因此scro缓存视频合并appll scan适合不需要排序的场景
「基本使用」
Scroll Scan 的遍服务器租用历与普通 Scrol面试技巧l 一样,初始化存在一点差别。
POST /my_index/my_type/_search?search_type=scan&scroll=1m&size=50
{
"query": { "match_all": {}}
}
需要指明参数:
-
search_type
:赋值为scan,表示采用 Scroll Scan 的方式遍历,同时告诉 Elasticsearch 搜索结果不需要排序。 - scroll:同上,传时间。
- size:与普通的 size 不同,这个 size 表示的是每个 shard 返回的 size 数,最终结果最大为
number_of_shards * size
。
「Scroll Sc面试问题大全及答案大全an与Scroll的区别」
- Scroll-Scan结果**「面试自我介绍简单大方没有排序」**,按i服务器价格ndex顺序返回,没有排序,可以优先级排序c语言提高取数据性能。
- 初始化时只返回
_scrol优先级越小越优先吗l_id
,没有具体的hits结果 - size控制的是每个分片的返回的数据量,而不面试技巧和话术大全是整个请求返回的数据量。
Sliced Scroll
如面试常见问题及回答技巧果你数据量很大,用Scroll遍历数github是什么据那确实是接受不了,现在Scroll接口可以并发来进行数据github是什么遍历了。
每个Scroll请求,服务器系统可以分成多个Slice请优先级队列求,可以理解为切片,各Slice独立并行,比用Scroll遍历要快很多倍。
POST /index/type/_search?scroll=1m
{
"query": { "match_all": {}},
"slice": {
"id": 0,
"max": 5
}
}
POST ip:port/index/type/_search?scroll=1m
{
"query": { "match_all": {}},
"slice": {
"id": 1,
"max": 5
}
}
上边的示例可以单独请求两块数据,最终五块数据合并的结果与直接scroll scan相同。
其中max是分块数,id是第几块。
❝
官方文档中建议max的值不要超过shard的数量,否则可能会导致内存爆炸github官网登陆入口。
❞
Search After
Search_after
是 ES 5 新引入的一种分页查询机制,其原理几乎就是和scroll一样,因此代码也几乎是一样的。
「基本优先级调度算法使用:」
第一步:
POST twitter/_search
{
"size": 10,
"query": {
"match" : {
"title" : "es"
}
},
"sort": [
{"date": "asc"},
{"_id": "desc"}
]
}
返回出的结果信息 :
{
"took" : 29,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 5,
"relation" : "eq"
},
"max_score" : null,
"hits" : [
{
...
},
"sort" : [
...
]
},
{
...
},
"sort" : [
124648691,
"624812"
]
}
]
}
}
上面的请求会为每一个文档返回一个包含sort排序值的数组。
这些sort排序值可以被用于优先级排序c语言search_after
参数里以便抓取下一页的数据。
比如优先级最高的运算符,我们可以使用最后的一个文档的优先级调度算法s面试问题ort排序值,将它传递给search_after
参数:
GET twitter/_search
{
"size": 10,
"query": {
"match" : {
"title" : "es"
}
},
"search_after": [124648691, "624812"],
"sort": [
{"date": "asc"},
{"_id": "desc"}
]
}
若我们想接着上次读取的结果进行读取下一页数据,第二次查询在第一服务器地址次查询时的语句基面试问题大全及答案大全础上添加search_after
,并指明从哪个数据后开始读取。
「基本原理」
es维护一个实时游标,它以上一次查询的最后一条记录为游标,方便对服务器租用多少钱一年下一页的查询,它是一个无面试自我介绍简单大方状态的查询,因此每次查询的都是最新的数据。
由于它采缓存视频变成本地视频用记录作为游标,因此 「SearchAfter要求doc中至少有一条全局唯一变量(每个文档具有一个唯一值的字段应该用作排序规范)」
「优缺点优先级英文」
「优点:」
- 无状态查询,可以防止在查询过程中,数据的变更无法及时反映到查询中。
- 不需面试常见问题及回答技巧要维护
scr面试常见问题及回答技巧oll_id
,不需要维护快照,因此可以避免消耗大量的缓存资源。
「缺点:」
- 由于无状态查询,因此在查询期间的变更可能会导致跨页面的不一值。
- 排序顺序可能会在执行期间发生变化,具体取决于索引的更新和删除。
- 至少需要制定一个唯一的不重复字段来排序。
- 它不优先级队列适用于大幅度跳页查询,或者全量导出,对第N页的跳优先级排序c语言转查询相当于对es不断重复的执行面试自我介绍3分钟通用N次面试search af服务器系统ter,而优先级英文全量导出则是在短时间内执行大量的重复查询。
SEARCH_AFTER
不是自由跳转到任意页面的解决方案,而是并行滚动多个查询的解决方案。
总结
分页方式 | 性能 | 优点 | 缺点 | 场景 |
---|---|---|---|---|
from + si面试问题大全及答案大全ze | 低 | 灵活性好,实现简单 | 深度分页问题 | 数据量比较小,能容忍深度分页问题 |
scroll | 中 | 解决了深度分页问题 | 无法反应数据的实时性(快照版本)维护成本高,需要维护一个 scroll_id | 海量数据的导出需要查询海量结果集的数据 |
s服务器earch_after | 高 | 性能最github官网好不存在深度分页github下载问题能够反映数据的实时变更 | 实现复杂,需要有一个全局唯一的字段连续分页的实现会比较复杂,因为每一次查询都需要上次查询的结果,它不适用于大幅度跳页查询 | 海量数据的分页 |
ES7版本变更
参照:www.el面试常见问题及回答技巧astic.co/guide/en/el…
在7.*
版本中,ES官方不再推服务器租用荐使用Scroll方法来进行深分页,而是推荐使用带PIT的search_after
来进行查询;
从7.*
版本开始,您可以使用SEARCH_AFTER
参数通过上优先级排序一页中的一组排序值检索下一页命中。
使用SEARCH_AFTER
需要优先级队列多个具有相同查询和排序值的搜索请求。
如果这些请求之间发生刷新,则结果的顺序可能会更改,从而导致页面之间的结果不一致。
为防止出现这种情况,您可以创建一个时间点(PIT)缓存视频变成本地视频来在搜索过程中保留当前索github中文官网网页引状态。
POST /my-index-000001/_pit?keep_alive=1m
返回一个PIT ID:
{
"id": "46ToAwMDaWR5BXV1aWQyKwZub2RlXzMAAAAAAAAAACoBYwADaWR4BXV1aWQxAgZub2RlXzEAAAAAAAAAAAEBYQADaWR5BXV1aWQyKgZub2RlXzIAAAAAAAAAAAwBYgACBXV1aWQyAAAFdXVpZDEAAQltYXRjaF9hbGw_gAAAAA=="
}
在搜索请求中指定PIT:
GET /_search
{
"size": 10000,
"query": {
"match" : {
"user.id" : "elkbee"
}
},
"pit": {
"id": "46ToAwMDaWR5BXV1aWQyKwZub2RlXzMAAAAAAAAAACoBYwADaWR4BXV1aWQxAgZub2RlXzEAAAAAAAAAAAEBYQADaWR5BXV1aWQyKgZub2RlXzIAAAAAAAAAAAwBYgACBXV1aWQyAAAFdXVpZDEAAQltYXRjaF9hbGw_gAAAAA==",
"keep_alive": "1m"
},
"sort": [
{"@timestamp": {"order": "asc", "format": "strict_date_optional_time_nanos", "numeric_type" : "date_nanos" }}
]
}
性能对比
分别分页获取优先级最高的运算符1 - 10
,49000 - 49010
,99000 - 99010
范围各10条数据(前提10w条面试自我介绍简单大方),性能大致是这样:
向缓存文件夹名称前翻页
对于向前翻页,ES中没有相应API,但是根据官方说法(github.com/elastic面试常见问题及回答技巧/ela…
- 对于某一页,正序
search_a面试自我介绍简单大方fter
该页的最后一条数据id服务器怎么搭建为下一页,则逆序search_after
该页的第一条数据id则为上一页。 - 国内论坛上,有人使用缓存来解决上一页的问题:elasticsearcgithub开放私库h.cn/question/7缓存英文7…
总结
- 如果优先级c语言数据量优先级c语言小(from+size在10000条内),或者只关注结果集的TopN数据,可以使用from/size 分页,简单粗暴
- 数据量大,深度翻页,后台批github汤姆处理任务(数据迁移)之类的任务,使用 scroll 方式
- 数据量大,深度翻页,用户实时、高并发查询需求,使用 search after 方式
个人思考
Scroll和search_after
原理基本相同,他们都采用了游服务器系统标的方式来进行深分页。
这种方式虽然能够一定程度上解决深分页问题。但是,它们并不是深分页问题的终极解决方案,深分页问题**「必须避免!!」**。
对于Scroll,无github汤姆可避免的服务器地址要维护scroll_id
和历史快照,并且,还必须保证scr服务器系统oll_id
的存活时间,这对服务器是一个巨大的负荷。
对于Search_After
,如果允许用户大幅度跳转页缓存面,会导致短时间内频繁的搜索动作,这github官网样的效率非常低下缓存视频变成本地视频,这也会增加服务器的负荷,同时,在查询过程中,索引的增删改会导致查询数据不一致或者排序变化,造成结果不准确。
Search_After
本优先级c语言身就是一种业务折中方案,它不允许指定跳转到页面,而只提供下一页的功能。
Scroll默认你会在后续将所有符合条件的数据都取出缓存来,所以,它只是搜索到了所有的符合条件的dgithub官网登陆入口oc_id
(这也是为什么官方推荐用doc_id
进行排序,因为本身缓存的就是优先级排序docgithub中文官网网页_id
,如果用其他字段排序会增加查询优先级队列量),并将它们排序后保存在协调节点(coordinate node),但是并没有将面试技巧所有数据进行fetch,而是每次scroll,读取siz面试技巧和注意事项e个文档,并返回此次读取的最后一个文档以及上下文状态,用以告知下一次需要从哪个shard的哪个文档之后开始读取。
这也是为什么官方不推荐scroll用来给用户进行实服务器是什么时的分页查询,而是适合于大批量的拉取数据,github官网登陆入口因为它从设计上就不是为了实时读取数据而设计的。