ES本地分片逆文档频率评分策略(Shard Local IDF)导致的评分异常原理解析

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: ES本地分片逆文档频率评分策略(Shard Local IDF)导致的评分异常原理解析

1、问题现象描述

假设有shard_local_idf索引(索引数据见文章末尾)

GET shard_local_idf/_search
{
  "query": {
    "match": {
      "title": "xiaomi shouji"
    }
  }
}


召回结果如下:

"hits" : [
      {
        "_index" : "shard_local_idf",
        "_type" : "_doc",
        "_id" : "11",
        "_score" : 1.9924302,
        "_routing" : "0",
        "_source" : {
          "title" : "xiaomi tv"
        }
      },
      {
        "_index" : "shard_local_idf",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.6282079,
        "_routing" : "1",
        "_source" : {
          "title" : "xiaomi shouji"
        }
      },
      {
        "_index" : "shard_local_idf",
        "_type" : "_doc",
        "_id" : "10",
        "_score" : 1.4816045,
        "_routing" : "1",
        "_source" : {
          "title" : "xiaomi tv"
        }
      }
      ...
    ]


2、原因分析

注意

如果对 相关性评分算法比较陌生,推荐先阅读以下文章:

Elasticsearch相关度评分算法(三):BM25(Okapi BM25)


2.1 词频得分(TF)相关性

对于_doc1和_doc11,两个文档词频都是1,他们在同一个索引,所以反词频一定相同,所以单就TF得分而言,这两个词得分肯定相同。


因此,对于上述问题,TF得分为常量,不是问题产生的主要原因。


2.2 反词频得分(IDF)相关性

假设对于搜索词“xiaomi”,两个文档的得分都是 x xx,对于_doc1 而言,由于假设 i d f idfidf 得分为 y yy 根据 i d f idfidf 计算函数可知 y yy > 0,而对于 _doc11 而言,tv 并未被命中,因此 i d f idfidf 得分为 0。


那么由此可计算两个文档的最终得分为:_doc1: x + y x + yx+y > _doc11: x xx

什么是逆文档频率评分(IDF)


2.3 eplain 查看执行计划

通过 explain 计算以下得分,如下

GET shard_local_idf/_search
{
  "explain": true, 
  "query": {
    "match": {
      "title": "xiaomi shouji"
    }
  }
}


对于 query:xiaomi shouji 查询结果如下:

微信截图_20221118202455.png


3、解决方案

3.1 开发和灰度环境或数据量不大的情况

search_type


dfs_query_then_fetch:使用从运行搜索的所有分片收集的信息,全局计算分布式词频。虽然此选项提高了评分的准确性,但它增加了每个分片的往返行程,这可能会导致搜索速度变慢。

query_then_fetch:(默认)为每个运行搜索的分片本地计算分布式词频。我们建议使用此选项进行更快的搜索,但评分可能不太准确。

测试环境设置:search_type = dfs_query_then_fetch 即表示在计算 i d f idfidf 的分值的时候,对全局进行计算,而不是 local_shard 。会牺牲一部分性能,换取准确性。这种方式适合于本地开发环境或者测试环境,或者生产环境中数据不对的情况下。


3.2 对于生产环境

对于生产环境,一般分布式数据库数据都不会太少,既然设计了多个分片,必然要考虑海量数据的情况。一般来说用 query_then_fetch 不太合适,会影响检索速度,牺牲用户体验。


生产环境真正的做法是避免分片不均衡,包括分片的大小、节点分片的分配数量、文档的均衡分配等。ES 本身通过 shard reblance 实现分片自动均衡策略,但是如果人工通过 routing 的方式分配数据,务必要保证数据按照某种机制,如分布式哈希表来控制数据的均衡分配,以避免这种情况的产生。


总结:在不了解分布式文档路由原理的前提下,不要随意使用 routing 来指定文档的分配机制。以免挖坑。

GET shard_local_idf/_search?search_type=dfs_query_then_fetch
{
  "explain": true, 
  "query": {
    "match": {
      "title": "xiaomi shouji"
    }
  }
}


4、测试数据

PUT shard_local_idf
{
  "settings": {
    "number_of_shards": 2,
    "number_of_replicas": 0
  }
}
PUT shard_local_idf/_bulk?routing=1&refresh=true
{"index":{"_id":1,"_type":"_doc"}}
{"title":"xiaomi shouji"}
{"index":{"_id":2,"_type":"_doc"}}
{"title":"huawei shouji"}
{"index":{"_id":3,"_type":"_doc"}}
{"title":"pingguo shouji"}
{"index":{"_id":4,"_type":"_doc"}}
{"title":"zhongxing shouji"}
{"index":{"_id":5,"_type":"_doc"}}
{"title":"sanxing shouji"}
{"index":{"_id":6,"_type":"_doc"}}
{"title":"bodao shouji"}
{"index":{"_id":7,"_type":"_doc"}}
{"title":"oppo shouji"}
{"index":{"_id":8,"_type":"_doc"}}
{"title":"lg shouji"}
{"index":{"_id":9,"_type":"_doc"}}
{"title":"vivo shouji"}
{"index":{"_id":10,"_type":"_doc"}}
{"title":"xiaomi tv"}
PUT shard_local_idf/_bulk?routing=0&refresh=true
{"index":{"_id":11,"_type":"_doc"}}
{"title":"xiaomi tv"}
{"index":{"_id":12,"_type":"_doc"}}
{"title":"huawei 12"}
{"index":{"_id":3,"_type":"_doc"}}
{"title":"pingguo 13"}
{"index":{"_id":14,"_type":"_doc"}}
{"title":"zhongxing 14"}
{"index":{"_id":15,"_type":"_doc"}}
{"title":"sanxing 51"}
{"index":{"_id":16,"_type":"_doc"}}
{"title":"bodao 16"}
{"index":{"_id":17,"_type":"_doc"}}
{"title":"oppo 17"}
{"index":{"_id":18,"_type":"_doc"}}
{"title":"lg 18"}
{"index":{"_id":19,"_type":"_doc"}}
{"title":"vivo 19"}
{"index":{"_id":20,"_type":"_doc"}}
{"title":"meizu 20"}


相关文章
|
6天前
|
存储 缓存 Java
什么是线程池?从底层源码入手,深度解析线程池的工作原理
本文从底层源码入手,深度解析ThreadPoolExecutor底层源码,包括其核心字段、内部类和重要方法,另外对Executors工具类下的四种自带线程池源码进行解释。 阅读本文后,可以对线程池的工作原理、七大参数、生命周期、拒绝策略等内容拥有更深入的认识。
什么是线程池?从底层源码入手,深度解析线程池的工作原理
|
4天前
|
负载均衡 监控 安全
Wi-Fi漫游深入解析:确保设备连接的有效策略
Wi-Fi漫游深入解析:确保设备连接的有效策略
23 9
|
17天前
|
域名解析 网络协议
DNS服务工作原理
文章详细介绍了DNS服务的工作原理,包括FQDN的概念、名称解析过程、DNS域名分级策略、根服务器的作用、DNS解析流程中的递归查询和迭代查询,以及为何有时基于IP能访问而基于域名不能访问的原因。
35 2
|
19天前
|
存储 安全 测试技术
|
6天前
|
监控 算法 数据可视化
深入解析Android应用开发中的高效内存管理策略在移动应用开发领域,Android平台因其开放性和灵活性备受开发者青睐。然而,随之而来的是内存管理的复杂性,这对开发者提出了更高的要求。高效的内存管理不仅能够提升应用的性能,还能有效避免因内存泄漏导致的应用崩溃。本文将探讨Android应用开发中的内存管理问题,并提供一系列实用的优化策略,帮助开发者打造更稳定、更高效的应用。
在Android开发中,内存管理是一个绕不开的话题。良好的内存管理机制不仅可以提高应用的运行效率,还能有效预防内存泄漏和过度消耗,从而延长电池寿命并提升用户体验。本文从Android内存管理的基本原理出发,详细讨论了几种常见的内存管理技巧,包括内存泄漏的检测与修复、内存分配与回收的优化方法,以及如何通过合理的编程习惯减少内存开销。通过对这些内容的阐述,旨在为Android开发者提供一套系统化的内存优化指南,助力开发出更加流畅稳定的应用。
17 0
|
13天前
|
负载均衡 网络协议 安全
DNS解析中的Anycast技术:原理与优势
【9月更文挑战第7天】在互联网体系中,域名系统(DNS)将域名转换为IP地址,但网络规模的扩张使DNS解析面临高效、稳定与安全挑战。Anycast技术应运而生,通过将同一IP地址分配给多个地理分布的服务器,并依据网络状况自动选择最近且负载低的服务器响应查询请求,提升了DNS解析速度与效率,实现负载均衡,缓解DDoS攻击,增强系统高可用性。此技术利用动态路由协议如BGP实现,未来在网络发展中将扮演重要角色。
39 0
|
19天前
|
开发者 安全 UED
JSF事件监听器:解锁动态界面的秘密武器,你真的知道如何驾驭它吗?
【8月更文挑战第31天】在构建动态用户界面时,事件监听器是实现组件间通信和响应用户操作的关键机制。JavaServer Faces (JSF) 提供了完整的事件模型,通过自定义事件监听器扩展组件行为。本文详细介绍如何在 JSF 应用中创建和使用事件监听器,提升应用的交互性和响应能力。
18 0
|
19天前
|
前端开发 Java UED
瞬间变身高手!JSF 与 Ajax 强强联手,打造极致用户体验的富客户端应用,让你的应用焕然一新!
【8月更文挑战第31天】JavaServer Faces (JSF) 是 Java EE 标准的一部分,常用于构建企业级 Web 应用。传统 JSF 应用采用全页面刷新方式,可能影响用户体验。通过集成 Ajax 技术,可以显著提升应用的响应速度和交互性。本文详细介绍如何在 JSF 应用中使用 Ajax 构建富客户端应用,并通过具体示例展示 Ajax 在 JSF 中的应用。首先,确保安装 JDK 和支持 Java EE 的应用服务器(如 Apache Tomcat 或 WildFly)。
27 0
|
21天前
|
监控 网络协议 Java
Tomcat源码解析】整体架构组成及核心组件
Tomcat,原名Catalina,是一款优雅轻盈的Web服务器,自4.x版本起扩展了JSP、EL等功能,超越了单纯的Servlet容器范畴。Servlet是Sun公司为Java编程Web应用制定的规范,Tomcat作为Servlet容器,负责构建Request与Response对象,并执行业务逻辑。
Tomcat源码解析】整体架构组成及核心组件
|
1月前
|
存储 NoSQL Redis
redis 6源码解析之 object
redis 6源码解析之 object
53 6

热门文章

最新文章

推荐镜像

更多