首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ES的深度分页解决方案

ES的深度分页解决方案

作者头像
春哥大魔王
发布2020-06-19 11:49:41
2.3K0
发布2020-06-19 11:49:41
举报

索引:共4T,5个索引,共100亿条数据

查询语句:

{ "query":{ "term":{ "app_servername":"set-app-heatontime01" } }, "size":10000, "sort": [ {"es_timestamp": "asc"}, ] }

符合条件结果总共5亿条数据。

scroll测试

拉取结果耗时:

拉取条数

10万

20万

50万

100万

200万

300万

500万

耗时

13.5s

30s

76s

158s

313s

560s

787s

es的并发scroll不适合深度翻页,只适合拉取所有数据。

es search_after也不适合做深度分页,分页多了,内存不够,将查询失败。

我们在分页的时候如果用from+size的话,from + size 默认不能超过1万条数据。

使用from + size方式是将请求达到分片节点上,如果有n个副分片,则查询数据是 n * (from+size) 如果from很大的话,会造成oom或者网络资源的浪费。

若使用scroll的话,尽管能读取许多数据,但是查询出来的结果都是无序的。

对于深度分页,到底有没有比较理想的解决方案,既能拉取比较多的数据,拉取的数据也都是有序的?那么你可以了解下search_after。

第一步

代码块

GET twitter/tweet/_search
{
    "size": 10,
    "query": {
        "match" : {
            "title" : "elasticsearch"
        }
    },
    "sort": [
        {"es_timestamp": "asc"},
        {"_uid": "desc"}
    ]
}

和我们正常查询没有什么区别,这里必须要使用sort进行排序。

同时sort中必须至少包含一个唯一的字段来进行排序,推荐使用_uid(必须有)。

同时日志中心的数据,也尽量将es_timestamp加上去一起排序。

若这里没有唯一的字段,那么每次获取结果将不够精确,影响使用。

返回的response如下:

代码块

  {
            "_index": "log.xxx.20181120_2",
            "_type": "logs",
            "_id": "AWcvRPOwqf9vJFGaVemX",
            "_score": null,
            "_source": {
               "mt_level": "WARN",
               "traceId__": "5919513527137007410",
               "mt_appkey": "xxxx",
               "mt_thread": "xxxx0",
               "es_timestamp": "2018/11/20 11:58:23 +0800",
               "mt_logger_name": "xxxx",
               "mt_datetime": "2018-11-20 11:58:23+0800",
               "message": " select scope cost:0\n",
               "mt_servername": "xxxxx"
            },
            "sort": [
               1542686303000,
               "logs#AWcvRPOwqf9vJFGaVemX"
            ]
         }

注意这里返回的sort结构。返回了每条数据的es_timestamp和_uid。

第二次分页

代码块

GET twitter/tweet/_search
{
    "size": 10,
    "query": {
        "match" : {
            "title" : "elasticsearch"
        }
    },
    "search_after": [1463538857, "tweet#654323"],
    "sort": [
        {"es_timestamp": "asc"},
        {"_uid": "desc"}
    ]
}

若我们想接着上次读取的结果进行读取下一页数据,第二次查询在第一次查询时的语句基础上添加search_after,并指明从哪个数据后开始读取。

search_after原理比较简单:

因为我们在sort中指明了唯一字段_uid,所以查询的数据整体肯定是有序的,在第二次查询时,同时将search_after指定的值作为查询条件(类似游标),指定从整个有序数据哪个位置继续查询。

缺陷:

search_after并不能代替from+ size和scroll,它每第二次读取时,必须要指定查询地址(游标search_after),实际使用时,只能一页一页的向下翻,而不能跳页查询。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-06-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 春哥talk 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • scroll测试
相关产品与服务
Elasticsearch Service
腾讯云 Elasticsearch Service(ES)是云端全托管海量数据检索分析服务,拥有高性能自研内核,集成X-Pack。ES 支持通过自治索引、存算分离、集群巡检等特性轻松管理集群,也支持免运维、自动弹性、按需使用的 Serverless 模式。使用 ES 您可以高效构建信息检索、日志分析、运维监控等服务,它独特的向量检索还可助您构建基于语义、图像的AI深度应用。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档