5.5-剖析分布式查询及相关性评分
分布式搜索的运⾏机制
-
Elasticsearch 的搜索,会分两阶段进⾏
-
第⼀阶段 - Query
-
第⼆阶段 - Fetch
-
-
Query-then-Fetch
Query 阶段
![](https://img.haomeiwen.com/i11385145/df6ea20d5d6a220f.png)
-
⽤户发出搜索请求到 ES 节点。节点收到请求后, 会以 Coordinating 节点的身份,在 6 个 主副分⽚中随机选择 3 个分⽚,发送查询请求
-
被选中的分⽚执⾏查询,进⾏排序。然后,每个分⽚都会返回 From + Size 个排序后的⽂档 Id 和排序值 给 Coordinating 节点
Fetch 阶段
![](https://img.haomeiwen.com/i11385145/688820f70623ddd7.png)
-
Coordinating Node 会将 Query 阶段,从每个分⽚获取的排序后的⽂档 Id 列表,重新进⾏排序。选取 From 到 From + Size 个⽂档的 Id
-
以 multi get 请求的⽅式,到相应的分⽚获取详细的⽂档数据
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 和内存,执⾏性能低下,⼀般不建议使⽤
-
相关性算分问题 Demo
-
写⼊ 3 条记录 “Good” / “Good morning” / “good morning everyone”
-
使⽤ 1 个主分⽚测试, Good 应该排在第⼀,Good DF 数值应该是 3
-
和 20 个主分⽚,测试
-
当 多个 个主分⽚时,3 个⽂档的算分都⼀样。 可以通过 Explain API 进⾏分析
-
在 3 个主分⽚上 执⾏ DFS Query Then Fetch,结果和⼀个分⽚上⼀致
本节知识点回顾
-
学习了分布式搜索 Query then Fetch 的机制
- Why / How
-
Query Then Fetch 带来的潜在问题
-
深度分⻚:使⽤ Search After
-
算分不准 :设置 1 个主分⽚ / 数据量⼤时,只需要保证⽂档平均分布 / DFS Query then Fetch
-
课程demo
DELETE message
PUT message
{
"settings": {
"number_of_shards": 20
}
}
GET message
POST message/_doc?routing=1
{
"content":"good"
}
POST message/_doc?routing=2
{
"content":"good morning"
}
POST message/_doc?routing=3
{
"content":"good morning everyone"
}
POST message/_search
{
"explain": true,
"query": {
"match_all": {}
}
}
POST message/_search
{
"explain": true,
"query": {
"term": {
"content": {
"value": "good"
}
}
}
}
POST message/_search?search_type=dfs_query_then_fetch
{
"query": {
"term": {
"content": {
"value": "good"
}
}
}
}