Lucene搜索引擎开发高级部分(索引的建立和优化)
1,文本的分析
对于不同的文本要使用不同的分析器
IndexWriter writer = new IndexWriter(indexPath,new StandardAnalyzer());
writer.addDocument(doc);
这是我们一般常用的方法,但是对于我们处理的文档中不仅含有中文文档(如还有法语)这样的情况,使用单一的分析器就会使得对于一种语言的文档分析的很好,而另外一种则不行,这样就要使用到addDocument方法的一个重载的方法:
writer.addDocument(doc,分析器实例);
2,分析器和解析器
解析器:
用来解析物理文件,从中提取所需的文本,如标题、正文、时间等,作用于物理文件。
常见的对word、excel、pdf等的解析。
分析器:
用来分析文本内容,或者说是分析文字。
3,分析器
Lucene自带的分析器:
1,WhitespaceAnalyzer
用于在空格处进行词语切分,将句子切分成词语块。
如:I love you切分成I,love,you
2,SimpleAnalyzer
在非字母字符处切分文本,并将其转换成小写形式。
如:I Love you切分成i,love,you
3,StopAnalyzer
在非字母字符处切分文本,然后小写化,再移除忽略词。
如:可爱的祖国,忽略词为“的”,切分成“可爱”和“祖国”
4,StandardAnalyzer
标准的分析器,基于某种语法规则,将文本切分成词语块。这种语法规则可以识别E-mail地址,首字母缩写词,汉语-日语-汉语字符,字母数字等。
5,其他
ChineseAnalyzer:单字切分
CJKAnalyzer:二分法切分
IKAnalyzer:词典法切分
6,可以开发自己的分析器
4,索引文件的格式
segments:索引块,其中含有只要的索引信息。
fum:存储了Field的名称。
fdt:存储了所有设置了保存属性(Store,YES)的Field数据
fdx:存储文档在fdt文件中为位置。
cfs:复合式索引格式的索引文件,相当于把多个索引文件合并起来,从而减少索引文件的数量。
5,索引的优化
建立索引就是为了搜索,搜索其实就是IO操作,当文件增大的时候IO操作会减慢,所以得优化。
优化的策略:
1,使用更好的硬盘
2,利用缓存减少磁盘读写频率。减少索引文件的大小和数量。(主要讲解)
(1)复合式索引格式
前面说的.cfs文件,是将所个索引文件合并起来的文件,从而减少索引文件的数量。
IndexWriter有setUseCompoundFile方法,通过这个方法可以设置是否使用复合式索引格式。默认是使用。
(2)调正索引优化参数
内存的IO速度比文件IO的速度快。所以我们可以现在内存中建立索引,然后将索引写到文件系统中。
Lucene有3个优化参数,可以优化磁盘写入频率和内存消耗
优化方式一:以下参数通过IndexWriter类来设定:
1,mergeFactor
控制索引块的合并频率和大小,默认值为10,Lucene默认在内存中存储10个Document对象,mergeFactor为10表示磁盘上的块数达到10的乘方时,Lucene会将这些块合并成一个段。(当Document对象到达10个的时候会合并成一个大的块,当大块到达10的话,会合并成一个更大的快......)到达一定Document的数量就合并成块的数量是由mergeFactor决定的
所以较大的mergeFactor适合批量的索引的情况,较小的mergeFactor适合交互性比较强的索引的情况。
较大的mergeFactor意味着低频率的合并,索引文件会增多,虽然这并不影响索引的性能,但是他会降低搜索的速度。
设置方法:IndexWriter的setMergeFactor(int mergeFactor)来设置mergeFactor的大小
2,maxMergeDocs
用来限制每个索引块的文档数量,默认的是Integer.Max_VALUE
设置方法:IndexWriter的setMaxMergeDocs(int maxMergeDocs)
3,maxBufferedDocs
用于限制内存中的文档数量,默认是10。这个值越大,在内存中存储的文档数量就越多,越消耗内存。同时磁盘IO越少。
maxBufferedDocs参数的意义在于使用更大的内存空间来换取更快的索引。
内存大的情况下,为了加快索引速度,我们要增大这个数的值。
设置方法:IndexWriter的setMaxBufferedDocs(int maxBufferedDocs)
优化方式二:以下是通过”先在内存中建立索引然后在写入到文件系统中“来实现索引的优化:
为了将索引在内存中缓存起来,我们需要一个”内存缓冲器“,需要IndexWriter的另一个构造器
public IndexWriter(Directory d,Analyzer a,boolean create) throws IOException
注意:第一个参数是Directory,他可以是RAMDirectory也可以是FSDirectory:
第一:如果是RAMDirectory表示在内存中建立索引,这样建立索引的速度很快,但是无法永久保存。
第二:如果是FSDirectory表示在硬盘中建立索引,可以永久保存,但是速度慢。
通过内存缓冲器将RAMDirectory的索引内容写到FSDirectory的步骤:
<1>建立基于RAMDirectory的索引。
RAMDirectorydirectoryInner =new RAMDirectory();
IndexWriterwriter = new IndexWriter(directoryInner,new IndexWriterConfig(Version.LUCENE_36,
new StandardAnalyzer(Version.LUCENE_36)));
<2>向基于RAMDirectory的索引中添加文档。
String content =“hello world”;
Documentdoc = new Document();
doc.add(new Field("content",content,Field.Store.YES,Field.Index.ANALYZED));
writer.addDocument(doc);
<3>建立基于FSDirectory的索引。
FSDirectorydirectoryOut = FSDirectory.open(new File("F:\\Lucene\\example\\index03"));
IndexWriterwriterOut =new IndexWriter(directoryOut,new IndexWriterConfig(Version.LUCENE_36,new StandardAnalyzer(Version.LUCENE_36)));
<4>把缓存在RAMDirectory中的所有的数据写入FSDirectory。
writerOut.addIndexes(new Directory[]{directoryInner});
writerOut.close();
优化方式三:索引本身的优化
IndexWriter的方法public void optimize() throws IOException
本方法用于将索引建立完成之后对索引文件进行合并的一种优化方式,该优化的好处只针对于搜索时的效率提高,对于索引的建立效率没有任何影响。
注意:索引优化比较耗时,所以建议在索引建立完毕之后进行优化,而不是在索引建立的时候进行优化。
Ps:IndexWriter的方法:
writer.setInfoStream(System.out);
这样设置之后在我们建立索引的时候,控制台就会打印出索引建立时的一些信息。对程序稍作修改就可以将信息输出到外部文件中,这样就行成了索引创建时的日志文件。这对于我们优化索引的建立有很大的帮助.