在 Elasticsearch(ES)中,当需要进行超过1万条数据的分页查询时,有几种常见的方法可以使用,每种方法都有其适用场景和优缺点。以下是几种主要的分页方法:
1.`from + size`分页
这是最基本的分页方式,通过指定`from`(起始位置)和`size`(每页数量)来获取数据。它简单易用,适用于数据量不大或不需要深度分页的场景。但是,当`from`值很大时,性能会下降,因为需要合并和排序所有分片返回的结果。ES 默认的`max_result_window`限制了最大分页数,通常为 10000,这意味着`from + size`的值不能超过这个限制。如果需要处理大量数据或深度分页,这种方式可能不是最佳选择。
2.`search_after`分页
`search_after`是一种基于游标的分页方法,适用于需要深度分页的场景。它通过使用上一页的最后一个文档的排序值来获取下一页数据,因此可以有效地避免深度分页的性能问题。这种方式的优点是性能较好,不存在深度分页问题,能够反映数据的实时变更。但是,它需要一个全局唯一的字段来排序,且实现相对复杂,每次查询都需要上次查询的结果。
使用示例
• 首次查询:
```json
GET /my-index-000001/_search
{
"size": 10,
"query": {
"match": {
"title": "elasticsearch"
}
},
"sort": [
{
"id": {
"order": "asc"
}
},
{
"_shard_doc": "asc"
}
]
}
```
• 后续查询:
```json
GET /my-index-000001/_search
{
"size": 10,
"query": {
"match": {
"title": "elasticsearch"
}
},
"sort": [
{
"id": {
"order": "asc"
}
},
{
"_shard_doc": "asc"
}
],
"search_after": [10000, 77050] // 上一页最后一个文档的排序值
}
```
3.`scroll`分页
`scroll`查询是一种在 ES 中扫描大量数据的常用方法。它通过在搜索结果中建立一个保持状态的`scroll_id`来实现。当您开始滚动时,ES 会返回第一批结果,并返回一个保持状态的 ID。使用此 ID,可以执行下一个滚动请求,以检索下一批结果。此过程可以重复进行,直到所有数据都被扫描完毕为止。`scroll`查询适用于需要遍历大量数据的场景,但牺牲了数据的实时性,因为`scroll`查询是基于初始查询时的快照数据。这种方式的优点是查询效率高,尤其适合于数据导出或批量处理,但缺点是需要维护`scroll_id`和历史快照,对服务器资源有一定的消耗。
使用示例
• 首次查询:
```json
POST /my-index-000001/_search?scroll=1m
{
"size": 100,
"query": {
"match": {
"message": "foo"
}
}
}
```
• 后续查询:
```json
POST /_search/scroll
{
"scroll": "1m",
"scroll_id": "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAD4WYm9laVYtZndUQlNsdDcwakFMNjU1QQ=="
}
```
• 删除游标:
```json
DELETE /_search/scroll
{
"scroll_id": "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAD4WYm9laVYtZndUQlNsdDcwakFMNjU1QQ=="
}
```
4.`PIT + search_after`分页
从 ES 7.10 版本开始,推荐使用`PIT + search_after`组合来实现深度分页。`PIT`(Point In Time)可以确保在查询过程中数据的一致性,而`search_after`则用于高效的分页查询。这种方式结合了`PIT`的一致性和`search_after`的高效性,适用于需要深度分页且对数据一致性有要求的场景。
使用示例
• 首次查询:
```json
GET /my-index-000001/_search
{
"size": 10,
"query": {
"match": {
"title": "elasticsearch"
}
},
"sort": [
{
"id": {
"order": "asc"
}
},
{
"_shard_doc": "asc"
}
],
"pit": {
"keep_alive": "1m"
}
}
```
• 后续查询:
```json
GET /my-index-000001/_search
{
"size": 10,
"query": {
"match": {
"title": "elasticsearch"
}
},
"sort": [
{
"id": {
"order": "asc"
}
},
{
"_shard_doc": "asc"
}
],
"search_after": [10000, 77050], // 上一页最后一个文档的排序值
"pit": {
"id": "39K1AwEPbXktaW5kZXgtMDAwMDAxFmZvclNBSGtUU0Uyc0xCb0pUdE1ZUkEAFkNfblFxQWwzVG5DZ0p6UmJUV2pNWWcAAAAAAAAATbUWYlNiMHU5MTFTbG1nWUZ1X3BpLXJCUQABFmZvclNBSGtUU0Uyc0xCb0pUdE1ZUkEAAA==",
"keep_alive": "1m"
}
}
```
总结
• `from + size`:适用于数据量不大或不需要深度分页的场景。
• `search_after`:适用于需要深度分页且对数据实时性有要求的场景。
• `scroll`:适用于需要遍历大量数据的场景,但牺牲了数据的实时性。
• `PIT + search_after`:适用于需要深度分页且对数据一致性有要求的场景。
根据具体需求选择合适的分页方法,可以有效提高查询性能和数据一致性。
标签:search,分页,after,查询,一万条,scroll,es,size From: https://blog.csdn.net/leijmdas/article/details/145072732