深度分页(Deep paging)
我们由前面知道,ES的数据是分片进行存储的,整体数据会被分布在不同的Primary分片上面,因此,如果一次比较深度的分页且排序的操作,成本将会比较大:
假如用户要查询5001-5050条数据,按照价格由低到高进行排序,那么ES的查询会发生什么?
因为数据是分片存储,因此需要每个分片都拿出自身的前5050条,然后整体排序后,取出5001-5050的数据,然后把无用的数据丢弃掉。这个成本随着数据量的增加将难以预估!
因此建议:
1、当你的数据超过1W,不要使用深度分页
2、返回结果不要超过1000个,500以下为宜
使用ES需要尽量避免深度分页查询(实际上,没有多少人会使用的到深度查询,例如百度,很少有人去点第100页的数据,可能第1,2页就不再继续看了),但如果确实有这样的需要,要怎么办呢?
使用Scroll search
Scroll search(滚动查询)
通过在_search后面指定scroll参数来使用:
scroll=1m,代表时间窗口是1分钟
GET /product/_search?scroll=1m
{
"query": {
"match_all": {}
},
"sort": [
{
"price": {
"order": "desc"
}
}
],
"size": 2
}
返回:
{
"_scroll_id" : "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAADbcWZEs2eGgxaXFRWUtmSWc3Yk8xTHZTZw==",
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 7,
"relation" : "eq"
},
"max_score" : null,
"hits" : [
{
"_index" : "product",
"_type" : "_doc",
"_id" : "1",
"_score" : null,
"_source" : {
"name" : "xiaomi phone",
"desc" : "shouji zhong de zhandouji",
"price" : 99999
},
"sort" : [
99999
]
},
{
"_index" : "product",
"_type" : "_doc",
"_id" : "MQhVI3IBIohknZNBAh6y",
"_score" : null,
"_source" : {
"name" : "balala nfc phone",
"desc" : "shouji zhong de hongzhaji",
"price" : 12999,
"tags" : [
"ff",
"we",
"asd"
]
},
"sort" : [
12999
]
}
]
}
}
移动游标,继续得到后面的数据:
GET /_search/scroll
{
"scroll":"1m", //延续scroll_id的有效时间
"scroll_id":"DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAADbcWZEs2eGgxaXFRWUtmSWc3Yk8xTHZTZw=="
}
但它有个问题:只能游标向后移动,也就是只能下一页,没办法上一页,不适合实时查询