Lucene索引库的简单优化
根据实际情况对索引库进行优化,可以提升创建索引和搜索的速度。
1、合并索引库片段文件
IndexWriter的optimize()方法已经过时,因为这个方法的效率很低。合并文件主要是使用IndexWriter的setMergeFactor(int)方法,但是在Lucene3.6版本中,该方法已过时,直接使用LogMergePolicy.setMergeFactor(int)方法代替。
当setMergeFactor(int)的参数值较小的时候,创建索引的速度较慢。当参数值较大的时候,创建索引的速度就比较快。大于10适合批量创建索引。
2、内存索引目录和文件系统索引目录结合使用
内存索引目录的操作速度非常快,所以我们在操作索引的时候可以把索引库从文件系统加载到内存中,操作完成后再写回文件系统。
内存中的索引文件写回到文建系统中的时候,我们需要对索引目录进行重建。比如原来文件系统中的索引目录有10个文件,加载到内存目录的时候是把10个文件拷贝一份到内存,然后我们添加了一个索引文件,内存中的索引目录文件数就变成11个,写会到文件系统的时候,内存索引目录文件数(11个)加上原来文件系统索引目录的文件数(10)就变成21个了,有10个文件是重复了,所以我们需要删除原来文件系统中的索引目录重新创建。
但是如果索引库是巨大的,不建议使用,因为所需的内存很大。
3、实现代码。
/**
* 索引库的优化
* @author Luxh
*/
public class IndexOptimizeTest {
//分词器
private Analyzer analyzer;
//索引存放目录
private Directory directory;
/**
* 初始化Analyzer和Directory
* @throws IOException
*/
@Before
public void before() throws IOException {
//建立一个标准分词器
//Version.LUCENE_36 表示匹配Lucene3.6版本
analyzer = new StandardAnalyzer(Version.LUCENE_36);
//在当前路径下建立一个目录叫indexDir
File indexDir = new File("./indexDir");
//创建索引目录
directory = FSDirectory.open(indexDir);
}
/**
* 合并索引片段文件
* @throws IOException
* @throws LockObtainFailedException
* @throws CorruptIndexException
*/
@Test
public void testMergeFactor() throws CorruptIndexException, LockObtainFailedException, IOException {
IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LUCENE_36,analyzer);
LogMergePolicy mergePolicy = new LogByteSizeMergePolicy();
//达到3个文件时就和合并
mergePolicy.setMergeFactor(3);
indexWriterConfig.setMergePolicy(mergePolicy);
IndexWriter indexWriter = new IndexWriter(directory,indexWriterConfig);
Book book = new Book();
book.setId(1);
book.setTitle("建筑的永恒之道");
book.setAuthor("亚历山大");
book.setContent("《建筑的永恒之道》提出了一个关于建筑设计、建筑和规划的新的理论、思想,该理论的核心是社会成员按照他们自己的存在状态设定他们生活的世界秩序,这一古老方式从根本上构成了新的后工业时代建筑的基础,这些建筑由人们创造。");
//建立Document
Document doc = new Document();
//Store指定Field是否需要存储,Index指定Field是否需要分词索引
doc.add(new Field("id",book.getId().toString(),Store.YES,Index.NOT_ANALYZED));
doc.add(new Field("title",book.getTitle(),Store.YES,Index.ANALYZED));
doc.add(new Field("author",book.getAuthor(),Store.YES,Index.ANALYZED));
doc.add(new Field("content",book.getContent(),Store.YES,Index.ANALYZED));
indexWriter.addDocument(doc);
indexWriter.close();
}
/**
* 内存索引目录和文件系统索引目录结合
* @throws IOException
*/
@Test
public void testDirectoryCombination() throws IOException {
//创建内存索引目录,把文件系统中的索引库加载进来
RAMDirectory ramDirectory = new RAMDirectory(directory);
IndexWriterConfig ramIndexWriterConfig = new IndexWriterConfig(Version.LUCENE_36,analyzer);
IndexWriter ramIndexWriter = new IndexWriter(ramDirectory,ramIndexWriterConfig);
Book book = new Book();
book.setId(1);
book.setTitle("建筑的永恒之道");
book.setAuthor("亚历山大");
book.setContent("《建筑的永恒之道》提出了一个关于建筑设计、建筑和规划的新的理论、思想,该理论的核心是社会成员按照他们自己的存在状态设定他们生活的世界秩序,这一古老方式从根本上构成了新的后工业时代建筑的基础,这些建筑由人们创造。");
//建立Document
Document doc = new Document();
//Store指定Field是否需要存储,Index指定Field是否需要分词索引
doc.add(new Field("id",book.getId().toString(),Store.YES,Index.NOT_ANALYZED));
doc.add(new Field("title",book.getTitle(),Store.YES,Index.ANALYZED));
doc.add(new Field("author",book.getAuthor(),Store.YES,Index.ANALYZED));
doc.add(new Field("content",book.getContent(),Store.YES,Index.ANALYZED));
ramIndexWriter.addDocument(doc);
ramIndexWriter.close();
IndexWriterConfig fsIndexWriterConfig = new IndexWriterConfig(Version.LUCENE_36,analyzer);
//创建新的索引目录或者覆盖原来的索引目录
fsIndexWriterConfig.setOpenMode(OpenMode.CREATE);
IndexWriter fsIndexWriter = new IndexWriter(directory,fsIndexWriterConfig);
//把内存中的索引库写到文件系统中
fsIndexWriter.addIndexes(ramDirectory);
fsIndexWriter.close();
}
}