lucene4.0特性

From Evernote:

lucene4.0特性

Clipped from: http://blog.mikemccandless.com/2012/07/lucene-400-alpha-at-long-last.html

内容总体上来自 Mike McCandless 的  

Lucene 4.0.0 alpha, at long last!

当作一个温故而知新的过程,记录在此。

4.0 alpha有许多重要的改进,基本的是:

3.6.0中所有deprecated的APIS已经被删除了

3.0之前的索引已经不在支持

MIGRATE.TXT 描述了怎样去更改你的应用代码

4.0 alpha和4.0 GA版本之间的索引格式不会再改变(除非为了fix严重的bug而需要更改),但在4.0 beta前,APIS还是会有调整。

插件式的 Codec

 4.0最大的变化是新引入的插件式的Codec框架,这一架构能完全控制索引的所有元素(terms, posings, stored fields, term vectors, deleted documents,segments infos, field infos)是如何写入的。你可以创建你自己或使用现成的codecs,同时你也可以为每一个基本的字段自定义postings format。

有一些有意思的核心codecs:

lucene40 是4.0.0中默认的codec.

lucene3x(只读)能读取lucene 3.x 格式的任何索引

SimpleText 以纯文本方式保存任何信息(这对学习,debug很有帮助,如何应用到生产系统将是一声灾难).

MemoryPostingsFormat   以快速及压缩的FST保存所有postings(terms, documents, positions, offsets) 在RAM中,这对于有限的postings是很有效果的(如primary key (id) field, date field, etc.)

PulsingPostingsFormat 针对那些低频的terms直接内联进terms dictionary,这样就可以减少一次硬盘查找时间。

AppendingCodec 避免了在写的时候进行询盘,这对于如 Hadoop DFS这类文件系统是非常有必要的。

如果你创建自己的codec,这也是很容易来确定是否所有的Lucene/Solr 测试用例是否能通过。如果有测试用例失败了,很有可能就是你的Codec有bug!

一个新的 4-dimensional postings API(to read fields, terms, documents,postings)代替了之前的postings API.

灵活的打分(Flexble scoring)

Lucene的打分机制现在是完全插件式的,其中默认的是 TF/IDF 向量空间模型. 你也可以创建自己的scoring model,或者使用核心scoring models中的一个(BM25,Divergence from Randomness, Language Models, 和 Infomations-based models). 每个文档(document)的normalization 值 也不再被限制到一个字节。各种新的集合统计数据也能被提供出来.

这些改进是 2011 Google Summer of Code Project的一部分(thank you David!).

这两个改进是相当重要,因为他们扫除了后续继续创新的障碍。现在已经很方便尝试文件格式 或者 lucene scoring models的改变。 一个最近出来的类似创新就是这个 灵巧的codec(由Flax的开发完成),通过将postings通过key/value保存在Redis中做到field更新。

Document Values

新版的 docuement values API  为每个文档保存强类型单值field, 这意味着这是一个可能替换Lucene field cache的方案。 这些值是在index阶段事先计算好,以 column-stride(所有文档某字段所有的值被保存在一起,可以理解成类似于列存储?)格式保存于索引中,这使得它比起field cache,在搜索时的初始化时间大大得到提升。这些值可以是固定的8,16,32,64位 ints, 也可以是可变长的(packed)ints; 浮点值,双精度值;6种类型的 byte数组(固定大小 or 可变大小;反向引用【dereferenced】?; straight or sorted).

New Field APIs

创建document fields 的API也已经改变了: Fieldable 和AbstractField 已经被删除, 从Field 类中重构出来的新的 FieldType,这包含field的值应该怎样被indexed。具体的经常使用到的新类已经事先创建好了:

StringField 索引string为一个单一的token, 没有norms 。例如可以把 primary key (id) field, 或者想进行排序的字段设置为StringField。

TextField 索引了完全tokenized String, 带上norms,同时也包括docs,term frequencies 和 positions.

StroredField 表示这个field的值只是保存使用。

XXXDocValuedsField 创建强类型的文档级别值的fields.

IntField,FloatField,LongField,DoubleField 为有效的范围查询和过滤器创造数字类型的字段。

如果这些feild 类没有一个可以应用的,你也可以创建你自己的FieldType, 然后构造一个Field通过传递一个名字,FieldType和值 。

 

note:原来那些老的APIs(使用index,store,termvector enums) 还是存在的(只不过已经是deprecated),为了方便迁移。

这些改变 是 2011 Google Summer of Code Project的一部分(thank you Nilola!).

其它主要改进(Other big changes)

lucene的terms 现在已经是二进制(byte[]); 默认情况下无边无际 UTF-8 编码的Strings, 以Unicode 排序顺序排列。但是Analyzer 是可以自由产生任意byte[]的token.(如CollationKeyAnalyzer就是这样做的).

新的DirectSpellChecker查找提示可以直接从任何一个lucene 索引,这样这避免了维护一个额外的spellchecker 索引。它使用了和FuzzyQuery一样的 fast Levenshtein automata(6+1 2013-2-17)。

Term offsets(term开始结束字符所在的位置)现在可以保存于postings,通过在索引字段时使用FieldInfo.IndexOption.Docs_AND_OFFSETS来实现。期望这对于不需要term vector而能快速highlighting有帮助。

新的AutomatonQuery匹配所有包含了提供的自动机中任一term的文档。WildQuery和RegexpQuery都是简单地构造出相关的自动机,然后再转到AutomatonQuery. 经典的QueryParse会r产生一个RegexpQuery如果你输入的是 filedName:/expression/ 或者 /expression against default field/.

优化(optimizations)

降了这些有趣的新特性以外,也还有一个惊人的性能提升。

如果你使用FuzzyQuery, 针对适度大小的索引你会看到 100-200倍的速度提升。

如果你搜索时使用Filter, 你也可以获取 X3的速度(这取决于filter的密度和query的复杂度),这得感谢于一个改变:filter的使用和删除文档保持一致。(6+1 2013-2-17)

如果在indexing时使用多线程,你将会看到吞吐率的提升,这是因为采用了 concurrent flushing. 现在你也可以使用大于2048M的 IndexWriter RAM buffer.

新的默认Terms dictionary BlockTree只需更少的RAM来保存terms index, 并且有时在terms不存在的情况下可以避免向disk进行查询。另外,field cache 也使用更少的RAM,这主要是不再为每个document保存一个单独的object,而是把character data 打包成共享的byte[] 块。 这直接减少了搜索时73%的内存使用量。

IndexWriter现在buffer term 数据使用byte[]而不是 char[], 这针对ASCII terms 将会少使用一半内存。

MultiTermQuery 现在重写了per-segment,并且cache 每个term的metadata 信息,这样可以在scoring时减少再次的查询。

如果一个BooleanQuery只包含Must TermQuery 条件,这时一个特定的ConjunctionTermScorer会被使用,可以得到25%的速度提升。

减少merge IO影响(reducing merge IO impact)

Merging是一个对IO,cpu相当敏感的操作,这很容易影响到正在进行的搜索。在4.0.0中我们通过两种方式来减少这方面的影响:

Rate-limit merge时的IO,这可以调用FSDirectory.setMaxMergeWriteMBPerSec

使用新的NativeUnixDirectory,针对所有merge 引发的IO,它会跳过操作系统的 IO cache层,而使用direct IO. 这会保证merge不会evict搜索使用的热门pages.

记得在linux上要设置swappiness为0,如果你想最大提升搜索的响应时间。

打开一个input 或者output文件的APIs(Directory.openInput and Directory.createOutput)现在要带上一个IOContext,用来描述需要怎样做(flush 还是merge),因此你可以创建自己的Directory,根据IOContext来改变相应接口的行为。

lucene codec是如何集成的

From Evernote:

lucene codec是如何集成的

lucene 4.0 后整体结构上一个最大的变化就是用户可以写各个codec,为扩展提供了极大的便利。

1. 那整体设置上是如何的呢?切入点是在哪里

codec

2. codec中使用哪些实现,通过

SPI(service provider interface) 来实现。

http://en.wikipedia.org/wiki/Service_provider_interface

3. codec 又是怎样初始化的呢? 也就是说如何配置使用哪个codec

    理解下spring的bean配置,可能会想到是否也利用同样的机制来配置决定使用哪个codec呢?

    同时再思考下,我们有时是不是经常对某一变量先new 一个default value,但同时又提供一个set方法,

     好让外界有机会根据自己的需要来modify这个value。

    没错,其实我们平时在用的这一套方法论也同样适用lucene中如何引用codec。

   对于Codec的总入口类 Codec,提供了一个获取default codec的方法:

  ……

 private static Codec defaultCodec = Codec.forName(“lucene41″);

  …….

  public static Codec getDefault(){

     return defaultCodec;

    }

spi实现的简单解释:

在resources目录下,创建 

完整classname的文件,

文件中内容是文件名对应接口的实现类,

在这个例子中就是各个不同版本的codec实现类。

目前的实现如果想升级某类field的format,必须升级整个codec,不能单独为一个field进行配置