search 的运行机制
node3在接收到用户请求时,先进行query阶段,此时为coordinating Node 角色
- node3 在六个主副分片中随机选择三个分片,发送search
- 被选中的分片会分别执行查询并拍寻,返回 from+size的文档id和排序值
- node3整合三个分片返回的from+size文档id,根据排序值排序后选取from到from+size的文档id
相关性算分
- 相关性算分在shard与shard之间是独立的,也就意味着同一个term的idf等值在不同的shard上是不同的,文档的相关性算分和它所处的shard相关。
- 在文档数量不多,会导致相关性算分严重不准的情况发生。
解决思路
- 设置分片数为1,从根本上排除问题,在文档不多时可以使用该方法,例如 百万到千万级别的文档数量
使用dfs query-then-fetch查询方式
- dfs 在拿到所有文档后再重新进行相关性算分,需要更多cpu和内存资源,性能较差,一般不建议使用。
sort
- es会默认采用相关性算分进行排序,用户可指定sort字段,来设置排序规则
- 按照字符串排序比较特殊,因为es有text和keyword两种类型,针对text类型
- 排序的过程实质是对字段原始内容排序的过程,这个过程倒排索引无法发挥作用,需要用到正排索引,也就是通过文档id和字段可以快速得到字段的原始内容。
es对此提供两种实现方式
- fielddata默认禁用
- doc values 默认启用 除了text类型
fielddata通过api开启
- 此时字符串是按照分词后的term排序,往往结果很难复合预期
- 一般是对分词做聚合分析时开启
- doc values 默认启用,在创建索引时关系,若需要再次开启,则需要reindex操作
- 可通过该字段获取fielddata或者doc values中存储的内容
from size 分页
from 起始位置 size 获取总数
深度分页 在数据分片存储的情况下如何获取前1000个文档
- 获取990-1000文档时,会在每个分片上都获取1000文档,然后再由coordinatingnode聚合素有的分片结果再排序选取前1000个
- 页数越深,处理文档越多,占用内存越多,耗时越唱,尽量避免深度分页,es通过index.max_result_window限定最多到10000条数据
scroll
遍历文档集合的api 以快照的方式来避免深度分页问题
- 不能用来做实时搜索,数据不是实时的
- 尽量不使用复杂的sort条件,使用_doc最高效
- 使用时稍显麻烦
search_after
避免深度分页的性能问题 提供实时的下一页文档获取功能
- 缺点时不能使用from参数 即不能指定页数
- 只能下一页 不能上一页
使用简单
- 正常搜索 但要指定sort值 并且保证值唯一
- 使用上一步最后一个文档的sort值进行查询
如何避免深度分页问题
- 通过唯一排序定位将每次要处理的文档数控制在size内
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。