Elasticsearch的深度分页
查看篇博客可以先查看下elasticsearch的DSL搜索方便理解:传送门接描述
一、深度分页分析
1.深度分页:(from:9999;size:10) 第9999后面的10条数据的话就会报错,因为es最大深度是支持搜索到底10000条数据,这个:index.max_result_window字段控制的,默认是10000条数据
POST 192.168.1.117:9200/sell/_doc/_search
{
"query": {
"match_all": {}
},
"from": 9999,
"size": 10
}
2.例如,我么有三个shard(分片),每个分片有10w条数据如果要查询9999-10009的数据,就会分别从每个分片中获取10009条数据,一共30027条数据,然后进行排序获取出10条数据,所以深度分页会给系统带来很大的压力
二、解决方式一(限制分页数)
我们可以限制分页的数量,而规避深度分页带来的性能影响,例如天猫会限制在80页
二、解决方式二(修改max_result_window初始值)
4.查看设置信息
GET 192.168.1.117:9200/sell/_settings
{
"sell": {
"settings": {
"index": {
"number_of_shards": "3",
"provided_name": "sell",
"max_result_window": "10000", // 默认值
"creation_date": "1605420740874",
"number_of_replicas": "1",
"uuid": "K4gnxKV3R5-AoxeMltlA5Q",
"version": {
"created": "7040299"
}
}
}
}
}
5.修改max_result_window的初始值,修改成100000
PUT 192.168.1.117:9200/sell/_settings
{
"index.max_result_window": 100000
}
6.之后再搜索(9999-10099)数据就不会报错了
二、解决方式二(使用scroll api)
1.滚动搜索(scroll api):会先查询出一部分数据然后依次查询,通过滚动的id来标记每次查询的位置,下一次查询就从该位置往后获取对应的数据,每次查询都是基于历史数据快照,如果此时有一个数据变在我们的搜索中是不会被体现出来的
POST 192.168.1.117:9200/sell/_search?scroll=1m // 1m表示的是此次会话的时间为1分钟
请求:
{
"query": {
"match_all": {}
},
"sort": ["_doc"], // 根据文档进行排序
"size": 5 // 每次查询的数据量
}
响应:
{
// _scroll_id就是标记查询的位置
"_scroll_id": "DnF1ZXJ5VGhlbkZldGNoAwAAAAAAAAAQFkJscVMzeEczVDBHOFM3RE5Qb2xCWkEAAAAAAAAAEhZCbHFTM3hHM1QwRzhTN0ROUG9sQlpBAAAAAAAAABEWQmxxUzN4RzNUMEc4UzdETlBvbEJaQQ==",
// 查询出的数据省略
}
2.执行下一次搜索
POST 192.168.1.117:9200/_search/scroll
{
"scroll_id": "DnF1ZXJ5VGhlbkZldGNoAwAAAAAAAAATFkJscVMzeEczVDBHOFM3RE5Qb2xCWkEAAAAAAAAAFRZCbHFTM3hHM1QwRzhTN0ROUG9sQlpBAAAAAAAAABQWQmxxUzN4RzNUMEc4UzdETlBvbEJaQQ==",
"scroll": "1m"
}