`
coderplay
  • 浏览: 575120 次
  • 性别: Icon_minigender_1
  • 来自: 广州杭州
社区版块
存档分类
最新评论

几个搜索相关的pdf(lucene, 分词等)

阅读更多

写文档时, 偶然发现很久以前的东西,给大家分享一下. 现在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与中文分词技术的研究及应用

    Lucene的组织结构清晰,主要包括以下几个部分: 1. **分析器**(Analyzer):用于将文本切分成词项(Term),并对词项进行标准化处理(如大小写转换、去除停用词等)。中文环境下,通常需要自定义分析器来实现中文...

    lucene学习pdf2

    在Lucene的学习中,你将接触到以下几个关键知识点: 1. **文档模型**:Lucene中的每个文档由多个字段组成,每个字段可以有不同属性,如是否被索引、是否被存储等。 2. **分词器(Tokenizer)**:这是将原始文本...

    Lucene开发详解.pdf

    Lucene默认提供的语言分析器(如SimpleAnalyzer和StandardAnalyzer)对于英文等西方语言的支持较好,但对于中文仅支持单字分词,这对于中文的搜索需求来说是远远不够的。为了提高中文检索的准确性和效率,通常需要...

    Lucene 实战(第2版)中文带书签.pdf

    8. **开发工具与API**:介绍了Lucene的API使用,包括索引API、搜索API、查询API等,以及相关的开发工具和调试方法,帮助读者更好地理解和掌握Lucene。 9. **问题解决**:书中还提供了常见问题和解决方案,有助于...

    Lucene In Action 第二版 高清中文版+附书源代码

    书中详细讲解了以下几个关键知识点: 1. **Lucene基础知识**:介绍Lucene的基本概念,如文档、字段、术语、倒排索引和查询解析,以及如何创建一个基本的Lucene应用。 2. **索引构建**:涵盖如何将结构化和非结构化...

    基于Lucene的搜索引擎在Struts中的应用.pdf

    在实际应用中,Lucene和Struts的结合通常涉及以下几个步骤: 1. **数据准备**:收集需要索引的文档数据,这可能包括数据库中的记录、文件系统中的文档或网页等。 2. **构建索引**:使用Lucene的索引模块对数据进行...

    开发自己的搜索引擎——Lucene+Heritrix

    3. **搜索引擎架构**: 构建搜索引擎通常包括以下几个步骤:网页抓取(由Heritrix完成)、预处理(包括HTML解析、链接提取、分词等)、索引创建(Lucene的主要任务)和查询处理。索引是搜索引擎的核心,它将网页内容...

    Lucene常用的Demo

    本篇文章将深入探讨Lucene的几个常见示例,包括`LuceneDemo`、`LuceneZJ`、`Lucene_HelloWorld`,帮助初学者快速理解Lucene的基本操作。 1. **Lucene_HelloWorld** 这个示例是入门Lucene的首选,它展示了如何创建...

    Lucene技术文档doc

    Lucene主要由以下几个关键组件构成: 1. **索引器(Indexer)**:负责读取文档,进行文本分析,并创建倒排索引。 2. **搜索器(Searcher)**:接收查询,通过索引找到匹配的文档,并计算相关度分数。 3. **分析器...

    lucene完整包,所有的包都有,非常全的

    在 Lucene 的核心设计中,它提供了以下几个关键知识点: 1. **索引构建**:Lucene 首先将非结构化的文本数据转换为可搜索的索引结构。这一过程包括分词(Tokenization)、词干提取(Stemming)、停用词过滤...

    lucene简单介绍及solr搭建使用

    搭建Solr的过程通常包括以下几个步骤: 1. **下载与解压**:从官方网站下载最新版本的Solr压缩包,然后解压到服务器的合适位置。 2. **配置Solr实例**:修改`solrconfig.xml`和`schema.xml`等配置文件,定义索引字段...

    基于LUCENE的网络搜索引擎系统研究及实现.pdf

    网络搜索引擎系统通常包含以下几个关键组件: 1. **爬虫(Crawler)**:负责在网络上抓取网页,是搜索引擎数据来源的基础。 2. **抓取管理器(Crawling Manager)**:控制爬虫的工作流程,包括网页的抓取频率、...

    lucene学习资料

    Lucene的核心概念主要包括以下几个方面: 1. **索引(Indexing)**:Lucene首先将非结构化的文本数据转化为可搜索的结构化表示,这一过程称为索引。索引过程中,Lucene会对文本进行分词(Tokenization),去除停用...

Global site tag (gtag.js) - Google Analytics