1、from和size是查询所有数据,然后剔除不要的部分
POST /my_index/my_type/_search
{
"query": { "match_all": {}},
"from": 100,
"size": 10
}
2、scroll是记录了一个读取的位置,保证下一次快速继续读取
scroll
查询阶段:将查询的结果集,doc_id列表保存在了一个上下文里
fetch阶段:根据size取回即可
POST /twitter/tweet/_search?scroll=1m
{
"size": 100,
"query": {
"match" : {
"title" : "elasticsearch"
}
}
}
Query阶段:每个shard将命中的结果( doc_id和_score) 按照 _score 顺序在上下文中创建一个优先队列快照,并通过scroll_id指向它,lastEmittedDoc指向上次访问的位置,最后将TOP(size)的doc id返回给协调节点。
Fetch阶段:协调节点将各个shard返回的结果再进行合并排序,最后通过doc_id查找返回结果的全量数据。之后更新各个分片上的上下文。
3、search_after
根据上一页最后一条数据来确定下一页的位置,因为每一页的数据依赖于上一页最后一条数据,所以无法完成跳页请求;在分页请求过程中如果有索引数据的增删改查,这些变更也会实时的反映到游标上。
核心思想记录上一次最后访问的位置
GET twitter/_search
{
"size": 10,
"query": {
"match" : {
"title" : "es"
}
},
"search_after": [124648691, "624812"],
"sort": [
{"date": "asc"},
{"_id": "desc"}
]
}
ES的排序方式
在query阶段就要进行排序,不全量查询的情况下怎么排序的?
- filter 查询 为 doc_id(Lucene 文件结构的当时索引时的先后顺序)
- 按照相关性得分排序( _score)
- 按照指定的字段排序 (term index中的顺序)
es默认分页查询方式
分页方式 | 性能 | 优点 | 缺点 | 场景 |
---|---|---|---|---|
from + size | 低 | 灵活性好,实现简单 | 深度分页问题 | 数据量比较小,能容忍深度分页问题 |
scroll | 中 | 解决了深度分页问题 | 无法反应数据的实时性(快照版本)维护成本高,需要维护一个 scroll_id | 海量数据的导出需要查询海量结果集的数据 |
search_after | 高 | 性能最好不存在深度分页问题能够反映数据的实时变更 | 实现复杂,需要有一个全局唯一的字段连续分页的实现会比较复杂,因为每一次查询都需要上次查询的结果,它不适用于大幅度跳页查询 |