6.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"
    ]
}
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设置关闭
    • 增加索引的速度 / 减少磁盘空间
  • 如果重新打开,需要重建索引
  • 当明确不需要做排序或聚合分析时可以关闭

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

算法小生Đ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值