您的位置:首页 > 产品设计 > UI/UE

记Lucene GEO Query的一点优化

2014-04-07 18:05 387 查看
目前我们使用的是Lucene 4.0,上面对GEO query的使用是这样的,索引阶段使用geo hash索引多个级别的geo grid,检索阶段获取geo grid做termquery,or起来,最后search之后在collector中按照距离做一次手动的过滤,这样做不方便的是geo query不能任意和其他query做or组合。

又查看了lucene spatial中的实现,是直接确定精度之后做索引,索引可能较快了,但是检索阶段需要使用PrefixQuery,感觉上灵活性较差,需要遍历每个最小的grid(具体仍需测试和权衡),检索阶段Geo Query是FilteredQuery(MatchAllDocsQuery, GEOFilter),GEO filter实际上主要接口是getDocIdSet(所以solr中很多filter是要缓存的),这样geo query是可以和其他query任意组合的。

我也按照这个思路写了个geo filter,实测一下发现比之前的性能有很大提高。

在我本机上做了一些简单测试,结果上用新的方式优于老的geo query(相关代码我提交在arts的test_geo_filter分支了)。索引上海所有上海,3000个附近搜索请求,不带任何关键字,结果如下:

1公里 老geo需要15.54秒, 新的7.32秒;
2公里 老geo需要31.41秒,新的13.71秒;
5公里 老geo需要65.71秒,新的34.85秒;
20公里 老geo需要91.50秒,新的48.75秒。

代码读下来,之所以提高有两处:

1.Collector中acceptDocsOutOfOrder()返回false,这样从不同term query返回的dicid每次需要在堆中选择一下;

2.对应的Term Query做了打分操作(DisconjunctionSumScorer),但实际scorer其实是在collector中完成,这样就浪费了。

另外发现query有个rewrite方法,可以对查询做优化,对于连续的And操作,有Conjunction Query做优化。

使用FilteredQuery经rewrite之后变成ConstantScoreQuery,没什么overhead。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: