Lucene03---索引位置的优化(内存和磁盘配合使用)

来源:互联网 发布:面向对象编程的语言 编辑:程序博客网 时间:2024/06/16 18:45
 

在前面的http://xdwangiflytek.iteye.com/blog/1391510 文章里我们使用Lucene3.5做了一个Demo,在Demo中我们实现了一个创建索引和搜索的功能。那么我们现在在回过头来看看在上面的Demo中,我们是将索引的位置放在本地磁盘中的,在上面最开始我也说了索引的位置可以是本地磁盘也可以是内存中,那么我们可以想想,如果索引放在内存中会怎么样?简单点来想,肯定是速度快没有IO操作,但是呢?程序一退出后就消失了,对吧,但是我们是不是可以考虑两种存放方式配合起来用呢?达到更好点的效果呢?

首先我们来说说创建的这两种位置的方式:

 

磁盘中:

Java代码 复制代码 收藏代码
  1. File indexFile = new File(indexPath);   
  2. Directory directory = FSDirectory.open(indexFile);  
File indexFile = new File(indexPath);Directory directory = FSDirectory.open(indexFile);

 

 内存中:

Java代码 复制代码 收藏代码
  1. Directory directory = new RAMDirectory();  
Directory directory = new RAMDirectory();
 

 

我们可以这样考虑,在程序运行的时候索引从内存进行读取,在程序退出的时候,再将索引保存到磁盘,但程序再运行的时候,再将磁盘中的索引放到内存中。这样的话是不是效率上好一点啊!

 

下面我们对昨天的Demo进行一个上面所说的简单优化:

 

FirstLucene02.java:

Java代码 复制代码 收藏代码
  1. package com.iflytek.lucene;   
  2.   
  3. import java.io.File;   
  4.   
  5. import org.apache.lucene.analysis.Analyzer;   
  6. import org.apache.lucene.analysis.standard.StandardAnalyzer;   
  7. import org.apache.lucene.document.Document;   
  8. import org.apache.lucene.index.IndexReader;   
  9. import org.apache.lucene.index.IndexWriter;   
  10. import org.apache.lucene.index.IndexWriterConfig;   
  11. import org.apache.lucene.queryParser.MultiFieldQueryParser;   
  12. import org.apache.lucene.queryParser.QueryParser;   
  13. import org.apache.lucene.search.Filter;   
  14. import org.apache.lucene.search.IndexSearcher;   
  15. import org.apache.lucene.search.Query;   
  16. import org.apache.lucene.search.ScoreDoc;   
  17. import org.apache.lucene.search.TopDocs;   
  18. import org.apache.lucene.store.Directory;   
  19. import org.apache.lucene.store.FSDirectory;   
  20. import org.apache.lucene.store.RAMDirectory;   
  21. import org.apache.lucene.util.Version;   
  22.   
  23. /**  
  24.  * @author xudongwang 2012-2-3  
  25.  *   
  26.  *         Email:xdwangiflytek@gmail.com  
  27.  */  
  28. public class FirstLucene02 {   
  29.   
  30.     /**  
  31.      * 源文件路径  
  32.      */  
  33.     private String filePath01 = "F:\\Workspaces\\workspaceSE\\BlogDemo\\luceneDatasource\\HelloLucene01.txt";   
  34.   
  35.     /**  
  36.      * 索引路径  
  37.      */  
  38.     private String indexPath = "F:\\Workspaces\\workspaceSE\\BlogDemo\\luceneIndex";   
  39.   
  40.     /**  
  41.      * 分词器,这里我们使用默认的分词器,标准分析器(好几个,但对中文的支持都不好)  
  42.      */  
  43.     private Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_35);   
  44.        
  45.     private Directory ramDir = null;   
  46.     /**  
  47.      * 搜索  
  48.      *   
  49.      * @param queryStr  
  50.      *            搜索的关键词  
  51.      * @throws Exception  
  52.      */  
  53.     public void search(String queryStr) throws Exception {   
  54.   
  55.         // 1、把要搜索的文本解析为Query对象   
  56.         // 指定在哪些字段查询   
  57.         String[] fields = { "name", "content" };   
  58.         // QueryParser: 是一个解析用户输入的工具,可以通过扫描用户输入的字符串,生成Query对象。   
  59.         QueryParser queryParser = new MultiFieldQueryParser(Version.LUCENE_35,   
  60.                 fields, analyzer);   
  61.         // Query:查询,lucene中支持模糊查询,语义查询,短语查询,组合查询等等,如有TermQuery,BooleanQuery,RangeQuery,WildcardQuery等一些类。   
  62.         Query query = queryParser.parse(queryStr);   
  63.         // 2、进行查询   
  64.         IndexReader indexReader = IndexReader.open(ramDir);   
  65.         IndexSearcher indexSearcher = new IndexSearcher(indexReader);   
  66.         // Filter 过滤器,我们可以将查出来的结果进行过滤,可以屏蔽掉一些不想给用户看到的内容   
  67.         Filter filter = null;   
  68.         // 10000表示一次性在数据库中查询多少个文档   
  69.         // topDocs 类似集合   
  70.         TopDocs topDocs = indexSearcher.search(query, filter, 10000);   
  71.         System.out.println("总共有【" + topDocs.totalHits + "】条匹配的结果");// 注意这里的匹配结果是指文档的个数,而不是文档中包含搜索结果的个数   
  72.         // 3、打印结果   
  73.         for (ScoreDoc scoreDoc : topDocs.scoreDocs) {   
  74.             int docSn = scoreDoc.doc;// 文档内部编号   
  75.             Document document = indexSearcher.doc(docSn);// 根据文档编号取出相应的文档   
  76.             File2Document.printDocumentInfo(document);// 打印出文档信息   
  77.         }   
  78.     }   
  79.   
  80.     /**  
  81.      * 优化创建索引,将索引存在在内存和磁盘配合使用  
  82.      *   
  83.      * @throws Exception  
  84.      */  
  85.     public void createIndexByYouHua() throws Exception {   
  86.         File indexFile = new File(indexPath);   
  87.         Directory fsDir = FSDirectory.open(indexFile);   
  88.   
  89.         // 1、启动时,将磁盘中的索引读取到内存中   
  90.         ramDir = new RAMDirectory(fsDir);   
  91.         IndexWriterConfig ramConf = new IndexWriterConfig(Version.LUCENE_35,   
  92.                 analyzer);   
  93.   
  94.         // 运行程序时操作内存中的索引   
  95.         IndexWriter ramIndexWriter = new IndexWriter(ramDir, ramConf);   
  96.         Document document = File2Document.file2Document(filePath01);   
  97.         ramIndexWriter.addDocument(document);   
  98.         ramIndexWriter.close();   
  99.   
  100.         // 2、退出时将内存中的索引保存到磁盘中   
  101.         IndexWriterConfig fsConf = new IndexWriterConfig(Version.LUCENE_35,   
  102.                 analyzer);   
  103.         IndexWriter fsIndexWriter = new IndexWriter(fsDir, fsConf);   
  104.         fsIndexWriter.addIndexes(ramDir);// 把另外几个索引库中的所有索引数据合并到当前的索引库中   
  105.         fsIndexWriter.close();   
  106.     }   
  107.   
  108.     public static void main(String[] args) throws Exception {   
  109.         FirstLucene02 lucene = new FirstLucene02();   
  110.         lucene.createIndexByYouHua();   
  111.         lucene.search("iteye");   
  112.     }   
  113.   
  114. }  
package com.iflytek.lucene;import java.io.File;import org.apache.lucene.analysis.Analyzer;import org.apache.lucene.analysis.standard.StandardAnalyzer;import org.apache.lucene.document.Document;import org.apache.lucene.index.IndexReader;import org.apache.lucene.index.IndexWriter;import org.apache.lucene.index.IndexWriterConfig;import org.apache.lucene.queryParser.MultiFieldQueryParser;import org.apache.lucene.queryParser.QueryParser;import org.apache.lucene.search.Filter;import org.apache.lucene.search.IndexSearcher;import org.apache.lucene.search.Query;import org.apache.lucene.search.ScoreDoc;import org.apache.lucene.search.TopDocs;import org.apache.lucene.store.Directory;import org.apache.lucene.store.FSDirectory;import org.apache.lucene.store.RAMDirectory;import org.apache.lucene.util.Version;/** * @author xudongwang 2012-2-3 *  *         Email:xdwangiflytek@gmail.com */public class FirstLucene02 {/** * 源文件路径 */private String filePath01 = "F:\\Workspaces\\workspaceSE\\BlogDemo\\luceneDatasource\\HelloLucene01.txt";/** * 索引路径 */private String indexPath = "F:\\Workspaces\\workspaceSE\\BlogDemo\\luceneIndex";/** * 分词器,这里我们使用默认的分词器,标准分析器(好几个,但对中文的支持都不好) */private Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_35);private Directory ramDir = null;/** * 搜索 *  * @param queryStr *            搜索的关键词 * @throws Exception */public void search(String queryStr) throws Exception {// 1、把要搜索的文本解析为Query对象// 指定在哪些字段查询String[] fields = { "name", "content" };// QueryParser: 是一个解析用户输入的工具,可以通过扫描用户输入的字符串,生成Query对象。QueryParser queryParser = new MultiFieldQueryParser(Version.LUCENE_35,fields, analyzer);// Query:查询,lucene中支持模糊查询,语义查询,短语查询,组合查询等等,如有TermQuery,BooleanQuery,RangeQuery,WildcardQuery等一些类。Query query = queryParser.parse(queryStr);// 2、进行查询IndexReader indexReader = IndexReader.open(ramDir);IndexSearcher indexSearcher = new IndexSearcher(indexReader);// Filter 过滤器,我们可以将查出来的结果进行过滤,可以屏蔽掉一些不想给用户看到的内容Filter filter = null;// 10000表示一次性在数据库中查询多少个文档// topDocs 类似集合TopDocs topDocs = indexSearcher.search(query, filter, 10000);System.out.println("总共有【" + topDocs.totalHits + "】条匹配的结果");// 注意这里的匹配结果是指文档的个数,而不是文档中包含搜索结果的个数// 3、打印结果for (ScoreDoc scoreDoc : topDocs.scoreDocs) {int docSn = scoreDoc.doc;// 文档内部编号Document document = indexSearcher.doc(docSn);// 根据文档编号取出相应的文档File2Document.printDocumentInfo(document);// 打印出文档信息}}/** * 优化创建索引,将索引存在在内存和磁盘配合使用 *  * @throws Exception */public void createIndexByYouHua() throws Exception {File indexFile = new File(indexPath);Directory fsDir = FSDirectory.open(indexFile);// 1、启动时,将磁盘中的索引读取到内存中ramDir = new RAMDirectory(fsDir);IndexWriterConfig ramConf = new IndexWriterConfig(Version.LUCENE_35,analyzer);// 运行程序时操作内存中的索引IndexWriter ramIndexWriter = new IndexWriter(ramDir, ramConf);Document document = File2Document.file2Document(filePath01);ramIndexWriter.addDocument(document);ramIndexWriter.close();// 2、退出时将内存中的索引保存到磁盘中IndexWriterConfig fsConf = new IndexWriterConfig(Version.LUCENE_35,analyzer);IndexWriter fsIndexWriter = new IndexWriter(fsDir, fsConf);fsIndexWriter.addIndexes(ramDir);// 把另外几个索引库中的所有索引数据合并到当前的索引库中fsIndexWriter.close();}public static void main(String[] args) throws Exception {FirstLucene02 lucene = new FirstLucene02();lucene.createIndexByYouHua();lucene.search("iteye");}}

 

 

运行结果:

总共有【1】条匹配的结果

name -->HelloLucene01.txt

content -->Hello, my name is wang xudong, I in iteye blog address is xdwangiflytek.iteye.com.

 

path -->F:\Workspaces\workspaceSE\BlogDemo\luceneDatasource\HelloLucene01.txt

size -->84

 

 

注意上面,添加的时候,索引文件可能会很多,所以这样就会产生更多的IO操作,影响效率,所以需要对索引文件进行优化,减少文件数量,从而减少IO操作。

在上面的优化创建索引的方法里的倒数第二行添加:

Java代码 复制代码 收藏代码
  1. fsIndexWriter.commit();   
  2. fsIndexWriter.optimize();//对索引文件进行优化,从而减少IO操作  
fsIndexWriter.commit();fsIndexWriter.optimize();//对索引文件进行优化,从而减少IO操作

 

 但是在Lucene3.5中这个方法提示过时了

 看源码提示:

Java代码 复制代码 收藏代码
  1. /** This method has been deprecated, as it is horribly  
  2.  *  inefficient and very rarely justified.  Lucene's  
  3.  *  multi-segment search performance has improved over  
  4.  *  time, and the default TieredMergePolicy now targets  
  5.  *  segments with deletions.  
  6.  *  
  7.  * @deprecated */  
  /** This method has been deprecated, as it is horribly   *  inefficient and very rarely justified.  Lucene's   *  multi-segment search performance has improved over   *  time, and the default TieredMergePolicy now targets   *  segments with deletions.   *   * @deprecated */

 

 

 这里还不知道Lucene3.5中对索引文件进行优化的方法,这里暂时留个问题。(?????)

有哪位知道的可以指点一下。

 

 

谢谢“gao2008ss”ok了,这种方式fsIndexWriter.forceMerge(1);,把上面的fsIndexWriter.optimize();替换为fsIndexWriter.forceMerge(1);

原创粉丝点击