首页 »编程综合 » lucenenet:Lucene.Net RangeQuery 效率确实低下 »正文
lucenenet:Lucene.Net RangeQuery 效率确实低下
来源: 发布时间:星期四, 2009年1月15日 浏览:18次 评论:0
很多文章提到 Lucene.Net RangeQuery 查询效率非常低下 我今天测试了 下 果然非常低下 而且结果也不正确 测试 代码: 索引 public void Index( count) { IndexWriter writer = IndexWriter(INDEX_DIR, Lucene.Net.Analysis.SimpleAnalyzer, true); _Count = count; Document doc = Document; for ( i = 0; i < count; i) { (IndexProgress != null) { IndexProgress(i); } iStr = .Format("{0:00000}", i); Field field = Field("Id", iStr, Field.Store.YES, Field.Index.UN_TOKENIZED); doc.Add(field); field = Field("Text", "Test " + i., Field.Store.YES, Field.Index.TOKENIZED); doc.Add(field); writer.AddDocument(doc); } (IndexProgress != null) { IndexProgress(count); } writer.Optimize; writer.Close; } 查找 public Search( begin, end) { IndexSearcher search = IndexSearcher(INDEX_DIR); try { bStr = .Format("{0:00000}", begin); eStr = .Format("{0:00000}", end); RangeQuery query = RangeQuery( Term("Id", bStr), Term("Id", eStr), true); //QueryParser qp = QueryParser("Text", Lucene.Net.Analysis.SimpleAnalyzer); //Query q = qp.Parse("Test"); //BooleanQuery bq = BooleanQuery; //bq.Add(query, BooleanClause.Occur.MUST); //bq.Add(q, BooleanClause.Occur.MUST); _StopWatch.Re; _StopWatch.Start; Hits hits = search.Search(query); retCount = hits.Length; _StopWatch.Stop; } catch(Exception e) { e.Message; } finally { search.Close; } StringBuilder report = StringBuilder; report.AppendLine("**************TestRange Report******************"); report.AppendFormat("Index count = {0}rn", _Count); report.AppendFormat("Begin {0} to {1}rn", begin, end); report.AppendFormat("ElapsedMilliseconds = {0}rn", ElapsedMilliseconds); report.AppendLine("**************End Report************************"); report.; }
这段代码 我尝试插入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 搜索过程 代码如下: (hitDocs.Count > min) { min = hitDocs.Count; } n = min * 2; // double # retrieved TopDocs topDocs = (sort null) ? searcher.Search(weight, filter, n) : searcher.Search(weight, filter, n, sort); length = topDocs.totalHits; ScoreDoc scoreDocs = topDocs.scoreDocs; float scoreNorm = 1.0f; (length > 0 && topDocs.GetMaxScore > 1.0f) { scoreNorm = 1.0f / topDocs.GetMaxScore; } end = scoreDocs.Length < length?scoreDocs.Length:length; for ( i = hitDocs.Count; i < end; i) { hitDocs.Add( HitDoc(scoreDocs[i].score * scoreNorm, scoreDocs[i].doc)); } 从这里我们可以看出length 被赋值为 topDocs.totalHits; 而不是topDocs.scoreDocs.Count 而这个 topDocs.totalHits 值始终是3000.也就是索引文件 记录总数 排除结果不对 问题不说 这种算法 效率也实在太低 而且限制你输出记录总数 范围只能在2000个记录以内 输出 范围超过2000个就无法查询(虽然你可以人为提高Clause 上限 但这将导致系统开销极大 增加) 对于垂直搜索来说 这种范围结合全文 查询是非常普遍 比如我们需要查某个名字 书名 且价格在某个范围内 这种需求用 lucene实现 基本就不可能了 这个测试使我对lucene 商业化应用 前景产生了怀疑 我打算调整Hubble.Net 设计和研发计划 优先考虑部分或 全部替换lucene
相关文章
读者评论
发表评论
|
|