专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »编程综合 » 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



0

相关文章

读者评论

发表评论

  • 昵称:
  • 内容: