广州linux

当前位置:   网站首页 >> 未命名

记Lucene GEO Query的一点优化

目前我们使用的是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。


发表我的评论

Hi,您需要填写昵称和邮箱!

  • 必填项