暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

33_Elasticsearch原理_分布式搜索

lin在路上 2020-05-25
286

Elasticsearch的搜索会分两个阶段:Query 和 Fetch

1 Query-then-Fetch

  • query

    • coordinating node接收到请求

    • 选择主分片(若有副本,则会在主分片及其对应副本中随机选择一台)发送查询请求

    • 被选中的分片执行查询,进行排序。

    • 分片返回From+size个排序后的文档id和排序值给Coordinating节点

  • fetch

    • coordinating node将query阶段获取到的文档id进行重新排序,选取From+Size个文档的id

    • 以multi get请求的方式,到相应的分片获取详细的文档数据

  • 潜在问题

    • 性能问题(深度分页)

      • 每个分片需要查询的文档个数=from+size

      • 协调节点需要处理:number_of_shard * (from + size)

    • 相关性算分

      • 每个分页都基于自己的分片上的数据进行相关度的计算。这会导致打分偏离的清空,特别是数据量很少时。相关性算分在分片之间是相互独立。当文档总数很少的情况下,如果主分片大于1,主分片越多结果越不准

2 解决算分不准的方法

  • 数据量方面

    • 数据量不大的情况下,将主分片数设置为1

    • 数据量大的时候,确保文档均匀分散在各个分片上,主要确保hash(_routing)均匀分布

  • 使用DFS Query Then Fetch

    • 搜索的URL中指定参数“_search?search_type=dfs_query_then_fetch”

    • 到每个分片把各分片的词频和文档频率进行搜集,然后完整的进行一次相关性算分,耗费更加多的CPU和内存,执行性能低下,一般不建议使用

3 深度分页

  • 限制最大查询的文档数量

    • 通过 index.max_result_window设置,默认10000

  • 通过Search After查询

    • 不支持指定页数(from),只能往下翻

    • 第一步搜索需要指定sort,并且保证值是唯一的(可以通过加入_id保证唯一性)

    • 使用上一次,最后一个文档的sort值进行查询

    • 通过唯一排序值定位,将每次要处理的文档数都控制在size,而不是之前的from+size个

  • Scroll API

    • 创建一个快照,有新的数据写入以后,无法被查询

    • 每次查询后,输入上一次的scroll id

    • 适用于大数据量分页,不支持向前


场景比较

  • from 和 size

    • 需要实时获取顶部的部分文档,例如查询最新的文档

  • Scroll API

    • 不支持向前翻页

    • 如整点数据全量导出

    • 对某个时间节点的数据进行操作

    • 不需要排序的大数据量查询,翻页

  • Search After

    • 不支持向前翻页

    • 需要指定唯一排序字段

    • 需要排序的大数据量的查询,翻页

3.1 Search After

 POST users/_doc
 {"name":"user1","age":10}
 
 POST users/_doc
 {"name":"user2","age":11}
 
 
 POST users/_doc
 {"name":"user2","age":12}
 
 POST users/_doc
 {"name":"user2","age":13}
 
 POST users/_count
 
 POST users/_search
 {
    "size": 1,
    "query": {
        "match_all": {}
    },
    "sort": [
        {"age": "desc"} ,
        {"_id": "asc"}    
    ]
 }
 
 POST users/_search
 {
    "size": 1,
    "query": {
        "match_all": {}
    },
    "search_after":
        [
          13,
          "G6w-sXEBuoXto2dXTeXA"],
    "sort": [
        {"age": "desc"} ,
        {"_id": "asc"}    
    ]
 }
 #其中search_after参数来自于上一次查询返回值的sort参数
复制

3.2 Scroll API

 POST users/_doc
 {"name":"user1","age":10}
 
 POST users/_doc
 {"name":"user2","age":20}
 
 POST users/_doc
 {"name":"user3","age":30}
 
 POST users/_doc
 {"name":"user4","age":40}
 
 POST /users/_search?scroll=5m
 {
    "size": 1,
    "query": {
        "match_all" : {
        }
    }
 }
 #设置5分钟的快照,每次获取一条记录
 
 POST users/_doc
 {"name":"user5","age":50}
 #快照创建完之后新增记录,用于验证快照内容的范围
 
 POST /_search/scroll
 {
    "scroll" : "1m",
    "scroll_id" : "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAWAWbWdoQXR2d3ZUd2kzSThwVTh4bVE0QQ=="
 }
 #scroll_id来源于创建快照时的返回值
复制



文章转载自lin在路上,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论