Lucene优化

转自:http://blog.csdn.net/wen158809179/article/details/7419254

 

1. 让程序中只有一个 IndexWriter。因为 IndexWriter 是对索引库目录下的文件进行操作,就算在多线程情况下,每次也只会有一个线程在访问这个文件。

   因此,程序中没必要维持多个 IndexWriter。

[java]   view plain copy
  1. /** 
  2.  * 使用 IndexWriter 进行保存或更新操作时, 
  3.  * 若不手动调用 IndexWriter 的 close 方法,数据并不会持久化到索引库中。 
  4.  * IndexWriter 一般只需要在程序退出的时候再关闭。 
  5.  * 因此,需要调用它的 commit 方法手动提交。需要特别注意。 
  6.  */  
  7. public class LuceneUtils {  
  8.        private static IndexWriter indexWriter;  
  9.        static {  
  10.               try {  
  11.                      /* 最好将目录放在配置文件 */  
  12.                      Directory directory = FSDirectory.open(new File("./indexDir/"));  
  13.                      /* 最好将版本放在配置文件 */  
  14.                      Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_30);  
  15.                      indexWriter = new IndexWriter(directory, analyzer, MaxFieldLength.LIMITED);  
  16.               } catch (Exception e) {  
  17.                      throw new RuntimeException(e);  
  18.               }  
  19.        }  
  20.        /** 
  21.         *  获取 IndexWriter 
  22.         */  
  23.        public static IndexWriter getIndexWriter() {  
  24.               return indexWriter;  
  25.        }  
  26.           /** 
  27.         * 关闭 IndexWriter 
  28.         */  
  29.        public static void closeIndexWriter() {  
  30.               try {  
  31.                      indexWriter.close();  
  32.               } catch (Exception e) {  
  33.                      throw new RuntimeException(e);  
  34.               }  
  35.        }  
  36. }  
  37.    

 2. 文件优化

  Lucene 会为每一次addDocument(document) 是在索引库目录下新增一个文件".cfs"后缀的文件。

   这意味我们的程序将便对越来越多的文件(但是默认情况下,最多也不会超过10个,当文件达到10个的时候,lucene 会将它们合并为一个大的文件)。意味着 IO 流的打开和关闭也将越来越多。这对效率的影响是比较大的。

   方式是调用 IndexWriter 的 IndexWriter.optimize() 或 indexWriter.setMergeFactor(int)

  IndexWriter.optimize() 被调用后,lucene 会立即将索引库目录下所有 ".cfs" 后缀的文件合并为一个大的文件。但是它的数据是不会改变的。

  indexWriter.setMergeFactor(int) 接收一个整型参数表示当 ".cfs" 文件达到多少数量时就自动合并。

 

3. 结合使用 FSDirectory 和 RAMDirectory

       /*文件系统的索引库,指向物理介质上真实存在的文件 */

       Directorydirectory = FSDirectory.open(new File("./indexDir/"));

       /*内存索引库,是在内存中模拟的一个索引库 */

       DirectoryRAMdir = new RAMDirectory();

   优缺点:

     FSDirectory 速度相对慢,但是 FSDirectory 的优点是能够在磁盘上持久化数据。

     RAMDirectory 读写数据的速度明显要快,但是缺点是数据在程序退出时就没有了。而且受限制于内存的大小。

   双剑合璧:

      1. 在程序启动的时候,将磁盘上的索引库加载到内存中来。

      2. 在程序退出的时候(或指定一个时机),将内存中的索引库数据状态同步会磁盘上。

    

      怎样将磁盘上的索引库加载到内存中来?

              Directory fsDir = FSDirectory.open(newFile("./indexDir/"));

              //使用带参构造器创建 RAMDirectory 对象。下面代码参数为指向磁盘索引库的 FSDirectory 对象 

              Directory RAMdir = newRAMDirectory(directory);

 

      怎样将内存中的索引库的数据同步回磁盘。

               Directory RAMdir = newRAMDirectory();

              Analyzeranalyzer = new StandardAnalyzer(Version.LUCENE_30);

              IndexWriter  ramIndexWriter = new IndexWriter(directory,analyzer,

                            MaxFieldLength.LIMITED);

              //ramIndexWriter.update.delete... 更新索引库

              /*同步数据回磁盘 */

              DirectoryfsDir = FSDirectory.open(new File("./indexDir/"));

              IndexWriter  fsIndexWriter = new IndexWriter(directory,analyzer, MaxFieldLength.LIMITED);

              fsIndexWriter.addIndexesNoOptimize(RAMdir);

             

              以上是一种默认情况,就是 fsIndexWriter 会采用创建或追加的方式来同步数据。

             -- 当磁盘上不存在对于索引库时则创建,并同步数据;否则,则追加和更新改变后的数据。

              IndexWriter的另一个构造其可以改变这种默认形式:

              IndexWriter  fsIndexWriter =

              new IndexWriter(directory,analyzer, [true | false], MaxFieldLength.LIMITED);

                     [true| false]: 若设置为 true,将总是创建或覆盖磁盘上的索引库。

               -- 当磁盘上不存在对于索引库时则创建,并同步数据;否则,则覆盖掉原有的索引库的全部数据。

                     若设置为 false。则只追加和更新改变后的数据。若原有数据库不存在,将报错。

     因此,一般用默认的就行了。true 的话要慎用。因为每次都推到重来,数据量很大的话,时间会比较久。

你可能感兴趣的:(Lucene)