39 - ES 分布式查询及相关性算分

分布式搜索的运行机制

  • Elasticsearch的搜索,会分两阶段进行
    • 第一阶段:Query
    • 第二阶段:Fetch
  • Query-then-Fetch

Query阶段

  • 用户发出搜索请求到ES节点。节点收到请求后,会以Coordinating节点的身份,在6个主副分片中随机选择3个分片,发送查询请求
  • 被选中的分片执行查询,进行排序。然后,每个分片都会返回From + Size个排序后的文档id和排序值给Coordinating节点

Fetch阶段

  • Coordinating Node会将Query阶段,从每个分片获取的排序后的文档id列表,从新进行排序。选取From到From + Size个文档的id
  • 以multi get请求的方式,到响应的分片获取详细的文档数据
query fetch示意图

Query Then Fetch潜在的问题

  • 性能问题
    • 每个分片上需要查的文档个数 = from + size
    • 最终协议调节点需要处理:number_of_shard + (from + size)
    • 深度分页
  • 相关性算分
    • 每个分片都基于自己的分片上的数据进行相关度计算。这会导致打分偏离的情况,特别是数据量很少时。相关性算分在分片之间是相互独立。当文档总数很少的情况下,如果主分片大于1,主分片越多,相关性算分越不准

解决算分不准的方法

  • 数据量不是很大的时候,可以将主分片数设置为1
    • 当数据量足够大的时候,只要保证文档均匀分散在各个分片上,结果一般就不会出现偏差
  • 使用DFS Query Then Fetch
    • 搜索URL中指定参数:“_search?search_type=dfs_query_then_fetch”
    • 到每个分片把各分片的词频和文档频率进行搜索,然后完整的进行一次相关性算分,耗费更多的CPU和内存,执行性能低下,一般不建议使用
准备数据

搜索结果会发现,数据从不同的分片中获取,最后进行合并的,如果数据分布在不同的分片,会发现算分基本上是一样的

POST messages/_search?search_type=dfs_query_then_fetch
{
  "explain": true,
  "query": {
  "term": {
    "content": {
      "value": "good"
    }
  }
  }
}

通过此查询语句发现算分不一样,且结果符合预期

你可能感兴趣的:(39 - ES 分布式查询及相关性算分)