Go最全ES深度分页查询详解_es分页查询(2),2024金三银四Golang大厂面试题来袭

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

三、From + Size 查询

1、准备数据

PUT user_index
{
  "mappings": {
     "properties": {
        "id":  {"type": "integer"},
        "name":   {"type": "keyword"}
     }
  }
}

POST user_index/_bulk
{ "create":  {  "\_id": "1" }}
{ "id":1,"name":"老万"}
{ "create":  {  "\_id": "2" }}
{ "id":2,"name":"老王"}
{ "create":  {  "\_id": "3" }}
{ "id":3,"name":"老刘"}
{ "create":  {  "\_id": "4" }}
{ "id":4,"name":"小明"}
{ "create":  {  "\_id": "5" }}
{ "id":5,"name":"小红"}

2、查询演示

无条件查询

POST user_index/_search

默认返回前10个匹配的匹配项。其中:
from:未指定,默认值是 0,注意不是1,代表当前页返回数据的起始值。
size:未指定,默认值是 10,代表当前页返回数据的条数。

指定from+size查询

POST user_index/_search
{
    "from": 0, 
    "size": 10,
    "query": {
        "match\_all": {}
    },
    "sort": [
        {"id": "asc"}    
    ]
}

3、max_result_window

es 默认采用的分页方式是 from+ size 的形式,在深度分页的情况下,这种使用方式效率是非常低的。
比如from = 5000, size=10, es 需要在各个分片上匹配排序并得到5000*10条有效数据,然后在结果集中取最后10条
数据返回,这种方式类似于mongo的 skip + size。

除了效率上的问题,还有一个无法解决的问题是,es 目前支持最大的 skip 值是 max_result_window ,默认为 10000
也就是当 from + size > max_result_window 时,es 将返回错误。

POST user_index/_search
{
    "from": 10000, 
    "size": 10,
    "query": {
        "match\_all": {}
    },
    "sort": [
        {"id": "asc"}    
    ]
}

这是ElasticSearch最简单的分页查询,但以上命令是会报错的。

报错信息,指window默认是10000。

"root\_cause": [
      {
        "type": "illegal\_argument\_exception",
        "reason": "Result window is too large, from + size must be less than or equal to: [10000] but was [10001]. See the scroll api for a more efficient way to request large data sets. This limit can be set by changing the [index.max\_result\_window] index level setting."
      }
    ],
    "type": "search\_phase\_execution\_exception",

怎么解决这个问题,首先能想到的就是调大这个window。

PUT user_index/_settings
{ 
    "index" : { 
        "max\_result\_window" : 20000
    }
}

然后这种方式只能暂时解决问题,当es 的使用越来越多,数据量越来越大,深度分页的场景越来越复杂时,如何解决这种问题呢?

官方建议:
避免过度使用 from 和 size 来分页或一次请求太多结果。

不推荐使用 from + size 做深度分页查询的核心原因:

  • 搜索请求通常跨越多个分片,每个分片必须将其请求的命中内容以及任何先前页面的命中内容加载到内存中。
  • 对于翻页较深的页面或大量结果,这些操作会显著增加内存和 CPU 使用率,从而导致性能下降或节点故障。

四、Search After 查询

search_after 参数使用上一页中的一组排序值来检索下一页的数据。
使用 search_after 需要具有相同查询和排序值的多个搜索请求。 如果在这些请求之间发生刷新,结果的顺序可能会发生变化,从而导致跨页面的结果不一致。 为防止出现这种情况,您可以创建一个时间点 (PIT) 以保留搜索中的当前索引状态。

时间点 Point In Time(PIT)保障搜索过程中保留特定事件点的索引状态。

注意⚠️:
es 给出了 search_after 的方式,这是在 >= 5.0 版本才提供的功能。
Point In Time(PIT)是 Elasticsearch 7.10 版本之后才有的新特性。

PIT的本质:存储索引数据状态的轻量级视图。

如下示例能很好的解读 PIT 视图的内涵。

#1、给索引user_index创建pit
POST /user_index/_pit?keep_alive=5m

#2、统计当前记录数 5
POST /user_index/_count

#3、根据pit统计当前记录数 5
GET /_search
{
  "query": {
        "match\_all": {}
    },
  "pit": {
	    "id":  "i6-xAwEKdXNlcl9pbmRleBZYTXdtSFRHeVJrZVhCby1OTjlHMS1nABZ0TEpMcVRuNFRxaWI4cXFTVERhOHR3AAAAAAAAIODBFmdBWEd2UmFVVGllZldNdnhPZDJmX0EBFlhNd21IVEd5UmtlWEJvLU5OOUcxLWcAAA==", 
	    "keep\_alive": "5m"
  },
  "sort": [
        {"id": "asc"}    
    ]
}
#4、插入一条数据
POST user_index/_bulk
{ "create":  {  "\_id": "6" }}
{ "id":6,"name":"老李"}

#5、数据总量 6
POST /user_index/_count

#6、根据pit统计数据总量还是 5 ,说明是根据时间点的视图进行统计。
GET /_search
{
  "query": {
        "match\_all": {}
    },
  "pit": {
	    "id":  "i6-xAwEKdXNlcl9pbmRleBZYTXdtSFRHeVJrZVhCby1OTjlHMS1nABZ0TEpMcVRuNFRxaWI4cXFTVERhOHR3AAAAAAAAIODBFmdBWEd2UmFVVGllZldNdnhPZDJmX0EBFlhNd21IVEd5UmtlWEJvLU5OOUcxLWcAAA==", 
	    "keep\_alive": "5m"
  },
  "sort": [
        {"id": "asc"}    
    ]
}

有了 PIT,search_after 的后续查询都是基于 PIT 视图进行,能有效保障数据的一致性。

search_after 分页查询可以简单概括为如下几个步骤。

1、获取索引的pit

POST /user_index/_pit?keep_alive=5m

2、根据pit首次查询

说明:根据pit查询的时候,不用指定索引名称。

GET /_search
{
  "query": {
        "match\_all": {}
    },
  "pit": {
	    "id":  "i6-xAwEKdXNlcl9pbmRleBZYTXdtSFRHeVJrZVhCby1OTjlHMS1nABZ0TEpMcVRuNFRxaWI4cXFTVERhOHR3AAAAAAAAIODBFmdBWEd2UmFVVGllZldNdnhPZDJmX0EBFlhNd21IVEd5UmtlWEJvLU5OOUcxLWcAAA==", 
	    "keep\_alive": "1m"
  },
  "sort": [
        {"id": "asc"}    
    ]
}

查询结果:返回的sort值为2.

hits" : [
      {
        "\_index" : "user\_index",
        "\_type" : "\_doc",
        "\_id" : "2",
        "\_score" : null,
        "\_source" : {
          "id" : 2,
          "name" : "老王"
        },
        "sort" : [
          2
        ]
      }
    ]

3、根据search_after和pit进行翻页查询

说明:
search_after指定为上一次查询返回的sort值。
要获得下一页结果,请使用最后一次命中的排序值(包括 tiebreaker)作为 search_after 参数重新运行先前的搜索。 如果使用 PIT,请在 pit.id 参数中使用最新的 PIT ID。 搜索的查询和排序参数必须保持不变。 如果提供,则 from 参数必须为 0(默认值)或 -1。

GET /_search
{
  "size": 1, 
  "query": {
        "match\_all": {}
    },
  "pit": {
	    "id":  "i6-xAwEKdXNlcl9pbmRleBZYTXdtSFRHeVJrZVhCby1OTjlHMS1nABZ0TEpMcVRuNFRxaWI4cXFTVERhOHR3AAAAAAAAIOJ7FmdBWEd2UmFVVGllZldNdnhPZDJmX0EBFlhNd21IVEd5UmtlWEJvLU5OOUcxLWcAAA==", 
	    "keep\_alive": "5m"
  },
  "sort": [
        {"id": "asc"}    
    ],
  "search\_after": [                                
    2
  ]
}

优缺点分析

search_after 查询仅支持向后翻页。
不严格受制于 max_result_window,可以无限制往后翻页。
单次请求值不能超过 max_result_window;但总翻页结果集可以超过。

思考🤔???

1、为什么采用search_after 查询能解决深度分页的问题?
2、search_after + pit分页查询过程中,PIT视图过期怎么办?
3、search_after 查询,如果需要回到前几页怎么办?

五、Scroll 遍历查询

ES官方不再推荐使用Scroll API 进行深度分页。 如果您需要在分页超过 10,000 个点击时保留索引状态,请使用带有时间点 (PIT) 的 search_after 参数。
相比于 From + size 和 search_after 返回一页数据,Scroll API 可用于从单个搜索请求中检索大量结果(甚至所有结果),其方式与传统数据库中游标(cursor)类似。

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

类似。

[外链图片转存中…(img-n0P39jdk-1715812034090)]
[外链图片转存中…(img-hj1iAOLC-1715812034090)]
[外链图片转存中…(img-aufUZmp7-1715812034091)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值