ES查询的步骤
1、Query阶段
1、收到用户请求,交由(coordinating node)协调者节点
2、coordinating node 随机选择所有分片/副本(保证所有都覆盖到),发送search request
3、被选中的分片分别执行查询并排序,返回from+size个文档id和排序值
4、coordinating node 整合数据,根据排序值再取from+size的文档id
2、Fetch阶段
1、通过Query阶段拿到文档Id列表,随后去对应的shard上获取文档详情数据
2、coordinating node 向相关分片发送multi_get请求
3、各个分片返回文档详细数据
4、coordinating node拼接结果并返回给客户
ES分页方式
1、From/Size
- from 开始位置
- size 获取总数
GET my_index/_search
{
"from":1,
"size":2
}
深度分页: 数据分片情况下如何拿到前1000个文档
- 获取从990~1000的文档时,会在每个分片上线获取1000个文档,由Coordinating Node聚合所有分片排序去1000个
- 页越深,处理文档越多,占用内存越多,耗时越长。避免深度分页,es通过index.max_result_window限定最多10000条数据(最多查到钱10000条数据)
2、Scroll
遍历文档集,以快照方式避免深度分页问题
- 不能实时搜索,因为数据是快照生成
- 尽量不要使用sort条件,使用_doc最高效
- 使用稍微复杂
- 调用过多会占用大量内存
查询方式:
1、发起一个scroll search,(5m是快照有效时间)
GET my_index/_search?scroll=5m
{
"size": 1
}
2、用第一步返回的_scroll_id
POST _search/scroll
{
"scroll": "5m",
"scroll_id": "..."
}
clear方式:
DELETE /_search/scroll
{
"scroll_id": ".."
}
或
DELETE /_search/scroll_all
3、Search_After
避免深度分页性能,提供实时下一页文档获取
- 确定不能使用from,指定页数
- 只能下一页,不能上一页
- 使用简单
方式:
1、正常搜索,必须指定sort值,保证唯一
2、使用上一步最后一个文档的sort值进行查询
request1:
GET test_search_index/_search
{
"size":1,
"sort":{
"age":"desc",
"_id":"desc"
}
}
response:
{
"hits":{}...
"sort":{"28","2"}
}
使用上一步的结果
request2:
GET test_search_index/_search
{
"size":1,
"search_after":[28,"2"],
"sort":{
"age":"desc",
"_id":"desc"
}
}