在建立索引的时候,一方面会建立倒排索引,以供搜索用;
一方面会建立正排索引,也就是 doc value,以供排序,聚合,过滤等操作使用。
doc value 是被保存在磁盘上的。此时如果内存足够,os 会自动将其缓存在内存中。
doc1: {"field_1": "value1", "field_2": "value1"}
doc2: {"field_1": "value2", "field_2": "value2"}
-
搜索请求发送到某一个
coordinate node,构建一个priority queue,长度以paging操作from和size为准,默认是 10 -
coordinate node将请求转发到所有shard,每个shard本地搜索,并构建一个本地的priority queue -
各个
shard将自己的priority queue返回给coordinate node,并构建一个全局的priority queue -
这个过程就是
query phase
由于 document 到达 coordinate node 还需要进行排序、分页、聚合等操作,所以部分数据可能是不需要的。为了减少网络传输的开销,priority quere 中只包含了 doc id
在 coordinate node 构建完 priority queue 之后,就发送 mget 请求去所有 shard 上获取对应的 document
各个 shard 将 document 返回给 coordinate node 后,coordinate node 将合并后的 document 结果返回给 client 客户端
假设有 5 个
shard,每个shard返回的priority queue都是根据某个field排序后的结果,现在我们需要获取排序后前四个document。首先每个
shard会返回内部排序后的前四个document,例如
6 3 2 1
7 5 3 2
3 2 1 0
9 4 2 1
4 3 2 1然后将
doc id返回给coordinate node处理
coordinate node会获取每个priority queue首位的document然后根据field对priority queue进行排序,得到
9 4 2 1
7 5 3 2
6 3 2 1
4 3 2 1
3 2 1 0那么就可以排除近一半的数据,前四的结果只可能存在于这半边
9 4 2 1
7 5 3
6 3
4此时使用
mget获取这些数据,然后进行排序即可获得结果
两个 document 排序,field 值相同
- 在不同的
shard上,可能排序不同 - 每次请求打到不同的
replica shard上,这样可能就会导致看到搜索结果不一样
解决方案:使用 preference
他可以决定哪些 shard 会被用来执行搜索操作
通过将 preference 设置为一个字符串,比如说 user_id,让每个 user 每次搜索的时候,都使用同一个 repliace shard 来执行,就不会发生 bouncing results 了。
document 文档路由默认是 _id 路由,如果需要根据其他 field 来确定 document 归属于哪个 shard 的话,可以设置routing=field
scroll 滚动搜索 es 内部支持的一种按批搜索模式,目的是解决大量数据查询带来的性能问题。
使用 scroll 搜索,es 会保存一个当前的快照,之后只会基于该旧快照提供数据搜索。
这个时期的数据变更,对用户是透明的。
scroll 和 paging 的区别是,scroll 是在服务内部完成滚动搜索获取大量数据,而 paging 只是为了获取当前页的数据。
scroll 同样会有分布式排序问题,推荐采用基于 _doc 进行排序的方式,性能较高。
假如 os cache 中的数据丢失
-
os disk 会同步从上一次 commit point 开始的所有 segment file 到磁盘上。
-
translog 会存储上一次 flush 开始的所有数据变更记录。
此时重启数据,首先会将 translog 文件中的变更记录进行回放,再重新将 segment 刷入 os cache 中,等待下一次 commit point 的发生。