Lucene.Net RangeQuery 效率确实低下
很多文章提到 Lucene.Net RangeQuery 的查询效率非常低下,我今天测试了一下,果然非常低下,而且结果也不正确。
测试 代码:
索引
查找
这段代码 我尝试插入3000条记录
搜索 0-1000条记录耗时 2秒多,如果搜索 0-2000条记录,lucene 会报错。
得到的结果也有问题,虽然 hits.HitDocs 的长度为1000,但hits.Length()的大小却是3000.
而hits.HitDocs 是私有成员,根本无法取出。
范围超过2000报错是因为clause的数量超过2000,而这个数量默认的最大值是2000.
从这个结果我大概判断,Lucene在进行范围查找的时候,并不是利用传统的B+树或者类似的算法计算范围,而是用全文的方法
计算范围,找到Score 值明显较大的记录,于是在查找00000 - 001000 的时候就产生 1001个Clause ,
分别是"00000", "00001", ..."001000", 用这1001个Clause
到全文索引中一一匹配得到Score值大的记录,然后输出。
Lucene 搜索过程的代码如下:
从这里我们可以看出length 被赋值为 topDocs.totalHits; 而不是topDocs.scoreDocs.Count
而这个 topDocs.totalHits的值始终是3000.也就是索引文件的记录总数。
排除结果不对的问题不说,这种算法的效率也实在太低,而且限制你输出记录总数的范围只能在2000个记录以内,输出
的范围超过2000个就无法查询(虽然你可以人为提高Clause的上限,但这将导致系统开销极大的增加)
对于垂直搜索来说,这种范围结合全文的查询是非常普遍的,比如我们需要查某个名字的书名,且价格在某个范围内。
这种需求用 lucene实现,基本就不可能了。
这个测试使我对lucene的商业化应用的前景产生了怀疑,我打算调整Hubble.Net 的设计和研发计划,优先考虑部分或
全部替换lucene。