写文档时, 偶然发现很久以前的东西,给大家分享一下. 现在lucene已经过了这个版本, 已经有OpenBitSet这种好东西了.~
1. lucene2.3.2的变更
2. 疱丁解牛分词器分析
3. 几种分词器精度和速度的比较
<!----><!---->
<!---->
Lucene2.3.2的变更
Author: Jeremy Chow(coderplay@gmail.com)
Last Modified: Aug 1st, 2008
一、运行时
<!---->1.
<!---->IndexWriter最大化地提高了现有的索引速度。第一,IndexWriter现在由内存的使用情况来决定刷新索引至磁盘,而不是之前用IndexWriter.setMaxBufferedDocs规定缓存的Docuement数量来决定刷新行为。第二,ConcurrentMergeScheduler使用后方(backgroud)线程(调用IndexWriter.setMergeScheduler
(new SerialMergeScheduler())保持向下兼容) 来进行合并操作,由此得到的好处是合并行为不会阻塞IndexWriter.addDocument操作。第三,现在对segment的合并操作是依据每个segment大小,而不再是依据它们所包含Document的数量。
<!---->2.
<!---->SortField.AUTO对long型起作用。在之前的lucene版本中,为排序自动检测Field类型时,数字首先被解释成int,如果解释失败,则认为是float。现在则先检测是否int,然后是否long,最后是float。
二、API
的变更
<!---->1.
<!---->新加了IndexWriter.setRAMBufferSizeMB(...),IndexWriter当缓存的Documents容量大于指定内存大小时进行刷新。同时,Token也添加了新的API,使用户使用char[]结合偏移量与长度来表示token
(避免为每个Token调用一次new String ())。
三、新特性
<!---->1.
<!---->新加了IndexReader.reopen() 方法用来重新打开已经存在的IndexReader。
<!---->2.
<!---->新加了IndexWriter.optimize(int
maxNumSegments) 用来局部优化值小于maxNumSegments 的片段
<!---->3.
<!---->新加了IndexWriter.optimize(int
maxNumSegments) 局部优化索引
<!---->4.
<!---->新加了IndexCommit.isOptimized()。
<!---->5.
<!---->新加了TokenFilter.reset()。
四、优化
1. CachingTokenFilter
现在使用一个迭代器来访问缓存在LinkedList内的Tokens。显著地提升了性能,特别是在Tokens数目比较大的情况。
2. 从实质上优化了IndexWriter怎么使用RAM来缓存Documents,使索引速度加快到之前的2~8倍。现在使用了一个简单的共享散列表记录在内存中的Postings。一个Term对应一个posting。这个表直接写入到一个segment中。
3. 消除了偶尔会发生在复合文件(compound
files)上的缓存到缓存拷贝(buffer to buffer copy)。
4. 去掉了Document中的同步机制,实际就是把存储Fields的Vector改成了ArrayList。
5. StandardTokenizer
(StandardAnalyzer)使用JFlex代替JavaCC生成Tokenizer,使其速度是以前的6倍。
6. 使用bulk-coping技术拷贝原始字节,加速邻接的未删除文档的合并。
7.加速了
ISOLatin1AccentFilter
。
五、重新打开索引文件
IndexReader
.reopen()
如果IndexReader实例调用此方法时,索引有变化,则生成一个新的IndexReader实例。
打开索引是非常昂贵的操作。此方法可以用来刷新已经存在的IndexReader,减少代价。此方法尝试只加载已经变化或新建立的片段(segement)。
如果索引自从打开后没有变化,则返回原来的IndexReader对象,否则会返回一个新的IndexReader对象。此时旧的IndexReader对象没有
关闭,只是不可用。
注意:
新打开的IndexReader对象可能会与旧的对象共享资源,据此,千万不要调用这些对象对索引的任何修改操作(例如:deleteDocument(int)
,
setNorm(int,
String, byte)
),除非旧IndexReader对象已经关闭。否则,其行为将是不可确定的。
你可以通过比较返回的IndexReader与原来的IndexReader来判断其是否真的重新打开了:
IndexReader reader = ...
...
IndexReader new = r.reopen();
if (new != reader) {
...
// reader was reopened
reader.close();
}
reader = new;
...
六、建立索引优化原理
以DocumentsWriter代替了之前的DocumentWriter。前者接受多个文档(Documents)的添加,并且直接把它们写入到一个单一的片段(segment)中。它比lucene2.2.0中用DocumentWriter为每个文档建立一个片段,然后将这些片段合并的方法更高效。
当加一篇文档时,它所存储的属性(Field)和词条向量(Term Vector)立即被写入到磁盘目录(假设不用RAM)。词频freq/prox
等词条信息(Posting),以词条为键值加入到Posting散列中。Posting散列表的每项维护着一个词频和prox组成的独立字节流。它包含多个文档的Posting数据。如果启用了向量,则为每个文档的每条词条都分配一个Posting向量(Posting
Vector)。向量的每个元素记录词条的偏移量、位置等信息。
当Posting散列已满(假设使用RAM)或者加入到RAM的文档数目足够大(在此,我们用文档数目,而不是RAM使用量来刷新索引)时,我们会建立一个真实的片段,把它刷新到磁盘,然后重置Posting散列。
加入文档时,我们首先由属性(Field)名来组织文档所有的属性,并为每个属性记录其Posting散列。处理完每个属性后,我们刷新它的词条向量。当到整个片段的时候,我们首先通过名称将属性(fields)排序,然后依次排序每个属性的Postings。
线程:
多条线程可以同时调用addDocument方法。DocumentsWriter内部有一个getThreadState的同步调用,它为当前线程式分配一个ThreadState对象。无论何时,同一线程将会得到同一ThreadState。因此,如果各线程为各自不同的内容建立索引,则可以更有效地使用RAM。之后,processDocument会在那个ThreadState之上被调用,它不用作同步(很多消耗在这一步)。这是lucene2.3.0最重要的改进。
最后,同步调用finishDocument刷新变化至磁盘目录。
每个ThreadState实例都有属于其自身的Postng散列。当我们使用过多RAM时,会通过合并多个线程状态(ThreadSate)中相同词条的Posting表中的文档ID(docIDs),刷新所有线程的Posting散列至一个片段中。
当IndexWriter调用刷新操作(flush),且autoCommit=false时,会执行刷新。此时,我们强制所有线程空闲,且确定它们都空闲后才刷新。这意味着,你可以由一个给定的线程调用刷新操作。
七、建索引速度测试
CPU:
Intel Dual CPU 2.00GHz,
内存:
1G
DDR400
文本材料大小
:
:
43.9
MB
文件数目
:
19997
个
分析器
:
lucene
标准
StandardAnalyzer
Lucene
版本:
2.2.0
生成索引大小
:
:
16,901,638
字节
耗时:
158094
微秒
110437
微秒
106328
微秒
Lucene
版本:
2.3.2
生成索引大小
:
16,177,772
字节
默认
16M
缓存耗时
:
15407
微秒
15500
微秒
设置
64M
缓存耗时
:
13578
微秒
13984
微秒
13359
微秒
15500
微秒
可以看出
2.3
比
2.2
建索引的速度要快
5~10
倍。
(不过现在看来是因为StandardAnalyzer变快了. )
分享到:
相关推荐
Lucene的组织结构清晰,主要包括以下几个部分: 1. **分析器**(Analyzer):用于将文本切分成词项(Term),并对词项进行标准化处理(如大小写转换、去除停用词等)。中文环境下,通常需要自定义分析器来实现中文...
在Lucene的学习中,你将接触到以下几个关键知识点: 1. **文档模型**:Lucene中的每个文档由多个字段组成,每个字段可以有不同属性,如是否被索引、是否被存储等。 2. **分词器(Tokenizer)**:这是将原始文本...
Lucene的整体架构包括以下几个核心组件: - **索引**:用于存储文档信息。 - **查询解析器**:处理用户输入的查询语句。 - **搜索器**:执行实际的索引搜索操作。 - **分析器**:负责文档和查询语句的分词和语言...
8. **开发工具与API**:介绍了Lucene的API使用,包括索引API、搜索API、查询API等,以及相关的开发工具和调试方法,帮助读者更好地理解和掌握Lucene。 9. **问题解决**:书中还提供了常见问题和解决方案,有助于...
书中详细讲解了以下几个关键知识点: 1. **Lucene基础知识**:介绍Lucene的基本概念,如文档、字段、术语、倒排索引和查询解析,以及如何创建一个基本的Lucene应用。 2. **索引构建**:涵盖如何将结构化和非结构化...
在实际应用中,Lucene和Struts的结合通常涉及以下几个步骤: 1. **数据准备**:收集需要索引的文档数据,这可能包括数据库中的记录、文件系统中的文档或网页等。 2. **构建索引**:使用Lucene的索引模块对数据进行...
3. **搜索引擎架构**: 构建搜索引擎通常包括以下几个步骤:网页抓取(由Heritrix完成)、预处理(包括HTML解析、链接提取、分词等)、索引创建(Lucene的主要任务)和查询处理。索引是搜索引擎的核心,它将网页内容...
本篇文章将深入探讨Lucene的几个常见示例,包括`LuceneDemo`、`LuceneZJ`、`Lucene_HelloWorld`,帮助初学者快速理解Lucene的基本操作。 1. **Lucene_HelloWorld** 这个示例是入门Lucene的首选,它展示了如何创建...
Lucene主要由以下几个关键组件构成: 1. **索引器(Indexer)**:负责读取文档,进行文本分析,并创建倒排索引。 2. **搜索器(Searcher)**:接收查询,通过索引找到匹配的文档,并计算相关度分数。 3. **分析器...
在 Lucene 的核心设计中,它提供了以下几个关键知识点: 1. **索引构建**:Lucene 首先将非结构化的文本数据转换为可搜索的索引结构。这一过程包括分词(Tokenization)、词干提取(Stemming)、停用词过滤...
搭建Solr的过程通常包括以下几个步骤: 1. **下载与解压**:从官方网站下载最新版本的Solr压缩包,然后解压到服务器的合适位置。 2. **配置Solr实例**:修改`solrconfig.xml`和`schema.xml`等配置文件,定义索引字段...
网络搜索引擎系统通常包含以下几个关键组件: 1. **爬虫(Crawler)**:负责在网络上抓取网页,是搜索引擎数据来源的基础。 2. **抓取管理器(Crawling Manager)**:控制爬虫的工作流程,包括网页的抓取频率、...
Lucene的核心概念主要包括以下几个方面: 1. **索引(Indexing)**:Lucene首先将非结构化的文本数据转化为可搜索的结构化表示,这一过程称为索引。索引过程中,Lucene会对文本进行分词(Tokenization),去除停用...