摘要:
从流程-细节-限制等进行分析,最后yy下性能
1 solr3.5 分布式groupby 关键流程
solr3.5 distribute groupby merger 结点需要向处理结点发3次网络请求,分布式facet为2次网络请求。
在 SearcherHandler.handleRequestBody总领下,进queryComponent的prepare->process->finished,
且process又分本地和分布式类型,并且两种类型process中又分 state 有序请求:search->topN->feild。
-->整个流程依然和solr一般分布式查询一致。查询框架的稳定。
-->groupby 性能不好的!!
2 querycomponent
prepare中
GroupingSpecification groupingSpec = new GroupingSpecification(); 总领grouping相关参数初始化。 其中 GROUP_TRUNCATE 针对topN相关性 groupby,也即截断groupby,在整个3序列都不支持,所以,默认值是false。在4.0也是不支持 group truncate 和func的。http://wiki.apache.org/solr/DistributedSearch
process中
分 group.distibuted.first group.distibuted.second。
-->这里的process是接受结点具体的工作,协调结点是对应 distributedProcess,在distributeProcess中有阶段state的概念。其中分布式阶段中,初始化 group.distibuted.first 在SearchGroupsRequestFactory的 constructRequest中赋值为true
group.distibuted.second 在 TopGroupsShardRequestFactory的 constructRequest中赋值为true
而SearchGroupsRequestFactory、TopGroupsShardRequestFactory正是distributeProcess中阶段任务
int nextStage = ResponseBuilder.STAGE_DONE; ShardRequestFactory shardRequestFactory = null; if (rb.stage < ResponseBuilder.STAGE_PARSE_QUERY) { nextStage = ResponseBuilder.STAGE_PARSE_QUERY; } elseif (rb.stage == ResponseBuilder.STAGE_PARSE_QUERY) { createDistributedIdf(rb); nextStage = ResponseBuilder.STAGE_TOP_GROUPS; } elseif (rb.stage < ResponseBuilder.STAGE_TOP_GROUPS) { nextStage = ResponseBuilder.STAGE_TOP_GROUPS; } elseif (rb.stage == ResponseBuilder.STAGE_TOP_GROUPS) { shardRequestFactory = new SearchGroupsRequestFactory(); //-->第一阶段 nextStage = ResponseBuilder.STAGE_EXECUTE_QUERY; } elseif (rb.stage < ResponseBuilder.STAGE_EXECUTE_QUERY) { nextStage = ResponseBuilder.STAGE_EXECUTE_QUERY; } elseif (rb.stage == ResponseBuilder.STAGE_EXECUTE_QUERY) { shardRequestFactory = new TopGroupsShardRequestFactory(); //-->第二阶段 nextStage = ResponseBuilder.STAGE_GET_FIELDS; } elseif (rb.stage < ResponseBuilder.STAGE_GET_FIELDS) { nextStage = ResponseBuilder.STAGE_GET_FIELDS; } elseif (rb.stage == ResponseBuilder.STAGE_GET_FIELDS) { shardRequestFactory = new StoredFieldsShardRequestFactory(); nextStage = ResponseBuilder.STAGE_DONE; } if (shardRequestFactory != null) { for (ShardRequest shardRequest : shardRequestFactory.constructRequest(rb)) { rb.addRequest(this, shardRequest); } } return nextStage; }
具体接受结点的 每一阶段都
CommandHandler commandHandler = secondPhaseBuilder.build();
commandHandler.execute(); //提交请求的 SearchGroupsResultTransformer serializer = new SearchGroupsResultTransformer(searcher);
commandHandler.processResult(result, serializer));
finished
合并结果和结构的结构化组织
限制
--> tuncate 和func 3序列和4.0 都不支持
--> 一次分布式请求,需要发起3次网络,n个结点,就是3n 次请求,相对facet 2n性能更差些
group.field Group based on the unique values of a field. The field must currently be single-valued and must be either indexed, or be another field type that has a value source and works in a function query - such as ExternalFileField. Note: for Solr 3.x versions the field must by a string like field such as StrField or TextField, otherwise a http status 400 is returned.
性能
-->优化思路:
调整分布式结构;优化接收结点具体group性能;添加各层cache调整分布式结构
如果合并请求,那么,一次返回内容更多、等待时机更长、结点资源hold更长时间。在分布查询和一般查询同时叠加的时候,资源共享不好。
如果不合并请求,那么,就分多次并发了。多次并发任务分解了,但是网络开销多了。 而目前普遍的做法就是并发+分阶段设计的。可以实现部分结果返回。当网络或者结点不稳定的时候。
另外一种改进方法:流式处理,每次topN结果往下一结点转移。这种系统维护成本比较高。有论文证明这种流式比较好的,忘了具体论文名称,回头找找。
优化接收结点具体group性能是当前主要的入口点了。而这里看源码,和facet类型,已经依赖了fieldCache了。
更底层的优化,就是重组索引结构,帮助快速group了。