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

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

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

磁盘中:

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

内存中:

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

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

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

FirstLucene02.java:

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值