elastic stack 那些事【6】

search 的运行机制

node3在接收到用户请求时,先进行query阶段,此时为coordinating Node 角色

  1. node3 在六个主副分片中随机选择三个分片,发送search
  2. 被选中的分片会分别执行查询并拍寻,返回 from+size的文档id和排序值
  3. node3整合三个分片返回的from+size文档id,根据排序值排序后选取from到from+size的文档id

相关性算分

  1. 相关性算分在shard与shard之间是独立的,也就意味着同一个term的idf等值在不同的shard上是不同的,文档的相关性算分和它所处的shard相关。
  2. 在文档数量不多,会导致相关性算分严重不准的情况发生。

解决思路

  1. 设置分片数为1,从根本上排除问题,在文档不多时可以使用该方法,例如 百万到千万级别的文档数量
  2. 使用dfs query-then-fetch查询方式

    1. dfs 在拿到所有文档后再重新进行相关性算分,需要更多cpu和内存资源,性能较差,一般不建议使用。

sort

  1. es会默认采用相关性算分进行排序,用户可指定sort字段,来设置排序规则
  2. 按照字符串排序比较特殊,因为es有text和keyword两种类型,针对text类型
  3. 排序的过程实质是对字段原始内容排序的过程,这个过程倒排索引无法发挥作用,需要用到正排索引,也就是通过文档id和字段可以快速得到字段的原始内容。
  4. es对此提供两种实现方式

    1. fielddata默认禁用
    2. doc values 默认启用 除了text类型

  1. fielddata通过api开启

    1. 此时字符串是按照分词后的term排序,往往结果很难复合预期
    2. 一般是对分词做聚合分析时开启
  2. doc values 默认启用,在创建索引时关系,若需要再次开启,则需要reindex操作
  3. 可通过该字段获取fielddata或者doc values中存储的内容

from size 分页

from 起始位置 size 获取总数

深度分页 在数据分片存储的情况下如何获取前1000个文档

  1. 获取990-1000文档时,会在每个分片上都获取1000文档,然后再由coordinatingnode聚合素有的分片结果再排序选取前1000个
  2. 页数越深,处理文档越多,占用内存越多,耗时越唱,尽量避免深度分页,es通过index.max_result_window限定最多到10000条数据

scroll

遍历文档集合的api 以快照的方式来避免深度分页问题

  1. 不能用来做实时搜索,数据不是实时的
  2. 尽量不使用复杂的sort条件,使用_doc最高效
  3. 使用时稍显麻烦

search_after

避免深度分页的性能问题 提供实时的下一页文档获取功能

  1. 缺点时不能使用from参数 即不能指定页数
  2. 只能下一页 不能上一页
  3. 使用简单

    1. 正常搜索 但要指定sort值 并且保证值唯一
    2. 使用上一步最后一个文档的sort值进行查询
  4. 如何避免深度分页问题

    1. 通过唯一排序定位将每次要处理的文档数控制在size内

你可能感兴趣的:(java)