Lucene.Net学习四——通过内存索引进一步提高索引的性能

在前面的例子中,利用的都是直接在文件系统上建立索引,如   Lucene.Net.Store.Directory indexDir = FSDirectory.Open(new DirectoryInfo(@"F:\lucene_index"));

其中Directory是一个抽象类,具有多态性,这里用过FSDirectory.Open()静态方法实现了一个FSDirectory实例,并给Directory赋值。

当然Lucene.Net也提供了内存中的索引RAMDirectory,在内存中的索引要比文件中的索引要快得多。下面通过一个例子来说明,同时对10000个文档建立索引,其它条件都相同。s代码如下:

static void Main(string[] args)
{
//构造索引存放的路径,初始化一个FSFSDirectory对象
Lucene.Net.Store.Directory FSDir = FSDirectory.Open(new DirectoryInfo(@"F:\lucene_index"));
//构造一个RAMDirectory
Lucene.Net.Store.Directory ramdir = new RAMDirectory();
//构造一个索引器,以文件系统为目标
IndexWriter IWFS = new IndexWriter(FSDir, new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29), true, new IndexWriter.MaxFieldLength(10000));
//构造一个索引器,以内存为目标
IndexWriter IWRAM = new IndexWriter(ramdir, new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29), true, new IndexWriter.MaxFieldLength(10000));
Field bookname = new Field("filmname", "射雕英雄传", Field.Store.YES, Field.Index.ANALYZED);

//在FSDirectory对10000个Document建立索引,输出所花费的时间
DateTime FSStart = DateTime.Now;
for (int i = 0; i < 10000; i++)
{
Document doc = new Document();
doc.Add(bookname);//向文档中添加域
IWFS.AddDocument(doc);
}
//关闭索引写入,一定要记得,否则会写不进去
IWFS.Close();
Console.WriteLine(string.Format("以文件系统为目标的索引花费时间为:{0}",(DateTime.Now-FSStart).TotalMilliseconds.ToString()));

//在RAMDirectory对10000个Document建立索引,输出所花费的时间
DateTime RAMStart = DateTime.Now;
for (int i = 0; i < 10000; i++)
{
Document doc = new Document();
doc.Add(bookname);//向文档中添加域
IWRAM.AddDocument(doc);
}
//关闭索引写入,一定要记得,否则会写不进去
IWRAM.Close();
Console.WriteLine(string.Format("以内存系统为目标的索引花费时间为:{0}", (DateTime.Now - RAMStart).TotalMilliseconds.ToString()));

}

可以看到内存索引所花费的时间比文件系统要少。

因此当修改参数:mergeFactor、maxMergeDocs、maxBufferedDocs以达到性能最优的时候,如过仍想进一步提高索性操作的性能,就可以把RAMDirectory作为缓冲器,进一步提高性能。也就是把先把索引建在内存中,当索引建好后,在向文件系统的索引合并。这里提到了一个新的操作方法,即索引的合并问题。在上面的代码后面加上如下代码:

//构造索引存放的路径,初始化一个FSFSDirectory对象
            Lucene.Net.Store.Directory FSDir = FSDirectory.Open(new DirectoryInfo(@"F:\lucene_index"));
            //构造一个RAMDirectory
            Lucene.Net.Store.Directory ramdir = new RAMDirectory();
            //构造一个索引器,以文件系统为目标     
            IndexWriter IWFS = new IndexWriter(FSDir, new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29), true, new IndexWriter.MaxFieldLength(10000));
          //构造一个索引器,以内存为目标
            IndexWriter IWRAM = new IndexWriter(ramdir, new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29), true, new IndexWriter.MaxFieldLength(10000));
            Field bookname = new Field("filmname", "射雕英雄传", Field.Store.YES, Field.Index.ANALYZED);

            //在FSDirectory对10000个Document建立索引,输出所花费的时间
            DateTime FSStart = DateTime.Now;
            for (int i = 0; i < 10000; i++)
            {
                Document doc = new Document(); 
                doc.Add(bookname);//向文档中添加域
                IWFS.AddDocument(doc);
            }
         
            Console.WriteLine(string.Format("以文件系统为目标的索引花费时间为:{0}",(DateTime.Now-FSStart).TotalMilliseconds.ToString()));

            //在RAMDirectory对10000个Document建立索引,输出所花费的时间
            DateTime RAMStart = DateTime.Now;
            for (int i = 0; i < 10000; i++)
            {
                Document doc = new Document();
                doc.Add(bookname);//向文档中添加域
                IWRAM.AddDocument(doc);
            }
            //关闭索引写入
            IWRAM.Close();
            Console.WriteLine(string.Format("以内存系统为目标的索引花费时间为:{0}", (DateTime.Now - RAMStart).TotalMilliseconds.ToString()));

            //合并索引
            IWFS.AddIndexesNoOptimize(new Lucene.Net.Store.Directory[]{ramdir});
            IWFS.Optimize();
            //关闭磁盘索引器
            IWFS.Close();

这里主要是调用了函数AddIndexesNoOptimize来实现。

根据以上思路,可以创建一个多线程的索引程序,每个线程都基于RAMDirectory创建索引,然后在合并。

如果是多磁盘系统,也可以单独对两块磁盘进行并行化索引。

  

posted @ 2012-03-30 20:56  郭远威  阅读(1200)  评论(1编辑  收藏  举报