elasticsearch深度分页索引

原文链接:https://blog.csdn.net/wang_kill/article/details/88692207

背景:es 深度分页索引效率问题

 

1.常见深度分页方式 from+size

es 默认采用的分页方式是 from+ size 的形式,在深度分页的情况下,这种使用方式效率是非常低的,比如

from = 5000, size=10000, es 需要在各个分片上匹配排序并得到5000*10000条有效数据,然后在结果集中取最后10000条

数据返回.

除了效率上的问题,还有一个无法解决的问题是,es 目前支持最大的 skip 值是 max_result_window ,默认

为  10000。也就是当 from + size > max_result_window 时,es 将返回错误.

当然,我们可以采用紧急规避方案,就是调整 max_result_window 的值。

curl -XPUT "127.0.0.1:9200/custm/_settings" -d '{ "index" : { "max_result_window" : 50000 } }'

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

为了满足深度分页的场景,es 提供了 scroll 的方式进行分页读取。原理上是对某次查询生成一个游标 scroll_id , 后续的查询只需要根据这个游标去取数据,直到结果集中返回的 hits 字段为空,就表示遍历结束。

scroll_id 的生成可以理解为建立了一个临时的历史快照,在此之后的增删改查等操作不会影响到这个快照的结果。

   1.先获取第一个 scroll_id,url 参数包括 /index/_type/ 和 scroll,scroll 字段指定了scroll_id 的有效生存期,以分钟为单位,过期之后会被es 自动清理。

curl -XGET 127.0.0.1:9200/db/info/_search?pretty&scroll=2m -d '{"query":{"match_all":{}}, "sort": ["_doc"]}'

   2.后续读取上一次查询返回的scroll_id 来不断的取下一页,如果srcoll_id 的生存期很长,那么每次返回的 scroll_id 都是一样的,直到该 scroll_id 过期,才会返回一个新的 scroll_id。请求指定的 scroll_id 时就不需要 /index/_type 等信息了。每读取一页都会重新设置 scroll_id 的生存时间,所以这个时间只需要满足读取当前页就可以,不需要满足读取所有的数据的时间,1 分钟足以。

curl -XGET '127.0.0.1:9200/_search/scroll?scroll=1m&scroll_id=cXDFERDGD45WEsdfd35DFEFDFX2ZnOzA

   3.所有文档获取完毕之后,需要手动清理掉 scroll_id 。虽然es 会有自动清理机制,但是 srcoll_id 的存在会耗费大量的资源来保存一份当前查询结果集映像,并且会占用文件描述符。所以用完之后要及时清理。使用 es 提供的 CLEAR_API 来删除指定的 scroll_id

删除掉所有索引上的 scroll_id    curl -XDELETE 127.0.0.1:9200/_search/scroll/_all

删掉指定的多个  srcoll_id           curl -XDELETE 127.0.0.1:9200/_search/scroll -d '{"scroll_id" : ["cXDFERDGD45WEsdfd35DFEFDFX2ZnOzA"]}'
3.search_after 的方式

上述的 scroll search 的方式,官方的建议并不是用于实时的请求,因为每一个 scroll_id 不仅会占用大量的资源(特别是排序的请求),而且是生成的历史快照,对于数据的变更不会反映到快照上。这种方式往往用于非实时处理大量数据的情况,比如要进行数据迁移或者索引变更之类的。那么在实时情况下如果处理深度分页的问题呢?es 给出了 search_after 的方式,这是在 >= 5.0 版本才提供的功能。

search_after 分页的方式和 scroll 有一些显著的区别,首先它是根据上一页的最后一条数据来确定下一页的位置,同时在分页请求的过程中,如果有索引数据的增删改查,这些变更也会实时的反映到游标上。

为了找到每一页最后一条数据,每个文档必须有一个全局唯一值,这种分页方式其实和目前 moa 内存中使用rbtree 分页的原理一样,官方推荐使用 _uid 作为全局唯一值,其实使用业务层的 id 也可以。
     第一页的请求和正常的请求一样

    curl -XGET 127.0.0.1:9200/db/info/_search

   {
    "size": 10,
    "query": {
        "term" : {
            "did" : 333
        }
    },
    "sort": [
        {"createdate": "asc"},
        {"_uid": "desc"}
    ]
}
     第二页的请求,使用第一页返回结果的最后一个数据的值,加上 search_after 字段来取下一页。注意,使用 search_after 的时候要将 from 置为 0 或 -1

curl -XGET 127.0.0.1:9200/order/info/_search
{
    "size": 10,
    "query": {
        "term" : {
            "did" : 333
        }
    },
    "search_after": [1463533345, "2039488283-ALT"],
    "sort": [
        {"createdate": "asc"},
        {"_uid": "desc"}
    ]
}

总结:search_after 适用于深度分页+ 排序,因为每一页的数据依赖于上一页最后一条数据,所以无法跳页请求。
---------------------
作者:nb009网
来源:CSDN
原文:https://blog.csdn.net/wang_kill/article/details/88692207
版权声明:本文为博主原创文章,转载请附上博文链接!

 

 

备注:参考:https://blog.csdn.net/andybegin/article/details/83864171 这篇文章提到,使用search_after 方式时,必须要设置from=0。

 

search_after 深分页

scroll 的方式,官方的建议不用于实时的请求(一般用于数据导出),因为每一个 scroll_id 不仅会占用大量的资源,而且会生成历史快照,对于数据的变更不会反映到快照上。

search_after 分页的方式是根据上一页的最后一条数据来确定下一页的位置,同时在分页请求的过程中,如果有索引数据的增删改查,这些变更也会实时的反映到游标上。但是需要注意,因为每一页的数据依赖于上一页最后一条数据,所以无法跳页请求。

为了找到每一页最后一条数据,每个文档必须有一个全局唯一值,官方推荐使用 _uid 作为全局唯一值,其实使用业务层的 id 也可以。

GET test_dev/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "age": 28
          }
        }
      ]
    }
  },
  "size": 20,
  "from": 0,
  "sort": [
    {
      "timestamp": {
        "order": "desc"
      },
      "_id": {
        "order": "desc"
      }
    }
  ]
}

    使用search_after必须要设置from=0。
    这里我使用timestamp和_id作为唯一值排序。
    我们在返回的最后一条数据里拿到sort属性的值传入到search_after。

使用sort返回的值搜索下一页:

GET test_dev/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "age": 28
          }
        }
      ]
    }
  },
  "size": 10,
  "from": 0,
  "search_after": [
    1541495312521,
    "d0xH6GYBBtbwbQSP0j1A"
  ],
  "sort": [
    {
      "timestamp": {
        "order": "desc"
      },
      "_id": {
        "order": "desc"
      }
    }
  ]
}


---------------------
作者:zhexiao27
来源:CSDN
原文:https://blog.csdn.net/andybegin/article/details/83864171
版权声明:本文为博主原创文章,转载请附上博文链接!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章