• 14.ElasticSearch系列之分布式特性及分布式搜索机制(三)


    1. 刨析分布式查询及相关性算分
    1.1 分布式搜索的运行机制
    • ElasticSearch的搜索,会分为两阶段进行
      • 第一阶段 Query
      • 第二阶段 Fetch
    • Query Then Fetch
    1.2 Query阶段
    • 用户发出搜索请求到ES节点。节点收到请求后,会已Coordinating节点的身份,在6个主副中随机选择3个分片,发送查询请求
    • 被选中的分片执行查询,进行排序。然后,每个分片都会返回FROM + Size个排序后的文档ID和排序值给Coordinating节点
    1.3 Fetch阶段
    • Coordinating节点会将Query阶段,从每个分片获取的排序后的文档ID列表,重新进行排序。选取From到From+Size个文档的ID
    • 以multi get请求的方式,到响应的分片上获取详细的文档数据
    1.4 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和内存,执行性能低下,一般不建议使用
    2. 排序与Doc Values&FieldData
    2.1 代码实操
    # 按日期排序,可以发现_score为null
    POST /kibana_sample_data_ecommerce/_search
    {
      "size": 5,
      "query": {
        "match_all": {
    
        }
      },
      "sort": [
        {"order_date": {"order": "desc"}}
      ]
    }
    # 多字段排序
    POST /kibana_sample_data_ecommerce/_search
    {
      "size": 5,
      "query": {
        "match_all": {
    
        }
      },
      "sort": [
        {"order_date": {"order": "desc"}},
        {"_doc":{"order": "asc"}},
        {"_score":{ "order": "desc"}}
      ]
    }
    # 对 text 字段进行排序。默认会报错,需打开fielddata
    POST /kibana_sample_data_ecommerce/_search
    {
      "size": 5,
      "query": {
        "match_all": {
    
        }
      },
      "sort": [
        {"customer_full_name": {"order": "desc"}}
      ]
    }
    # 打开 text的 fielddata,然后再次执行上述查询
    PUT kibana_sample_data_ecommerce/_mapping
    {
      "properties": {
        "customer_full_name" : {
              "type" : "text",
              "fielddata": true,
              "fields" : {
                "keyword" : {
                  "type" : "keyword",
                  "ignore_above" : 256
                }
              }
            }
      }
    }
    # 关闭 keyword的 doc values
    PUT test_keyword
    PUT test_keyword/_mapping
    {
      "properties": {
        "user_name":{
          "type": "keyword",
          "doc_values":false
        }
      }
    }
    
    PUT temp_users
    PUT temp_users/_mapping
    {
      "properties": {
        "name":{"type": "text","fielddata": true},
        "desc":{"type": "text","fielddata": true}
      }
    }
    POST temp_users/_doc
    {"name":"Jack","desc":"Jack is a good boy!","age":10}
    
    # 打开fielddata 后,查看 docvalue_fields数据
    POST  temp_users/_search
    {
      "docvalue_fields": [
        "name","desc"
        ]
    }
    # 查看整型字段的docvalues
    POST  temp_users/_search
    {
      "docvalue_fields": [
        "age"
        ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    2.2 排序的过程
    • 排序是针对字段原始内容进行。倒排索引无法发挥作用
    • 需要用到正排索引。通过文档ID和字段快速得到字段原始内容
    • ElasticSearch两种实现方法
      • Fielddata
      • Doc Values(列式存储,对Text类型无效)
    2.3 Doc Values与Field Data对比
    Doc ValuesField Data
    何时创建索引时,和倒排索引一起创建搜索时动态创建
    创建位置磁盘文件JVM Heap
    优点避免大量内存占用索引速度快,不占用额外磁盘空间
    缺点降低索引速度,占用额外磁盘空间文档过多时,动态创建开销大,占用过多JVM Heap
    2.3 关闭Doc Values
    • 默认启用,可以通过mapping设置关闭
      • 增加索引的速度 / 减少磁盘空间
    • 如果重新打开,需要重建索引
    • 当明确不需要做排序或聚合分析时可以关闭

    欢迎关注公众号算法小生沈健的技术博客

  • 相关阅读:
    面向过程 VS 面向对象
    Python升级之路( Lv9 ) 文件操作
    进程和线程详解
    tomcat7和tomcat8的websocket区别
    ai智工作室22级第三次训练赛
    循环结构 ----- for/in 语句 与 for/of语句
    Visual Studio Code使用
    STM32之HAL开发——CubeMX串行Flash文件系统源码讲解
    解决从PDF复制文字后乱码问题
    汉字风格迁移篇--中文字体的多任务对抗学习
  • 原文地址:https://blog.csdn.net/SJshenjian/article/details/127435248