Google

Archives

Online free book: Search User Interface

Marti Hearst 刚完成的一本新书, Search User Interfaces. 令人兴奋的是, 网上可以在网上免费阅读!  Marti 是 UC Berkeley 教授, 也是搜索用户接口设计方面的专家。这本相关博客: SearchUpTicious.

url:  http://searchuserinterfaces.com/book/

Incoming search terms for the article:search user interface (3)Search User Interfaces (2)

使用Java Tar Package读取*.tar 或*.tar.gz 文件

使用Java Tar Package读取*.tar 或*.tar.gz 文件

Java Tar Package com.ice.tar 实现了一个tar 文档输入输出io包。使用方式接近java 中自带的 java.util.zip 包,所以也该非常容易上手,如果使用国java的zip包的话。

而且配合java 的中的GZIPInputStream 使用,就很容易实现.tar.gz 文件的访问。
步骤:
1. 读取文件,生成GZIPInputStream 流
2. 把1中生成的GZIPInputStream流传给 Java Tar Package 中的TarInputStream 流
过程非常简单,代码如下
private void visitTARGZ(P parser, File targzFile) throws IOException {
FileInputStream fileIn = null;
BufferedInputStream bufIn = null;
GZIPInputStream gzipIn = null;
TarInputStream taris = null;
try {
fileIn = new FileInputStream(targzFile);
bufIn = new BufferedInputStream(fileIn);
gzipIn = new GZIPInputStream(bufIn); //first [...]

lucene影响索引速度的因素-MergeFactor, MaxMergeDocs, RAMBufferSizeMB

版本:Java lucene2.4

在索引算法确定的情况下,最为影响Lucene索引速度有三个参数--IndexWriter中的 MergeFactor, MaxMergeDocs, RAMBufferSizeMB 。这些参数无非是控制内外存交换和索引合并频率,从而达到提高索引速度。当然这些参数的设置也得依照硬件条件灵活设置。

MaxMergeDocs

该参数决定写入内存索引文档个数,到达该数目后就把该内存索引写入硬盘,生成一个新的索引segment文件。
所以该参数也就是一个内存buffer,一般来说越大索引速度越快。
MaxBufferedDocs这个参数默认是disabled的,因为Lucene中还用另外一个参数(RAMBufferSizeMB)控制这个bufffer的索引文档个数。
其实MaxBufferedDocs和RAMBufferSizeMB这两个参数是可以一起使用的,一起使用时只要有一个触发条件满足就写入硬盘,生成一个新的索引segment文件。

RAMBufferSizeMB

控制用于buffer索引文档的内存上限,如果buffer的索引文档个数到达该上限就写入硬盘。当然,一般来说也只越大索引速度越快。
当我们对文档大小不太确定时,这个参数就相当有用,不至于outofmemory error.

MergeFactor

这个参数是用于子索引(Segment)合并的。
Lucene中索引总体上是这样进行,索引现写到内存,触发一定限制条件后写入硬盘,生成一个独立的子索引-lucene中叫Segment。一般来说这些子索引需要合并成一个索引,也就是optimize(),否则会影响检索速度,而且也可能导致open too many files。
MergeFactor 这个参数就是控制当硬盘中有多少个子索引segments,我们就需要现把这些索引合并冲一个稍微大些的索引了。
MergeFactor这个不能设置太大,特别是当MaxBufferedDocs比较小时(segment 越多),否则会导致open too many files错误,甚至导致虚拟机外面出错。

Note: Lucene 中默认索引合并机制并不是两两合并,好像是多个segment 合并成最终的一个大索引,所以MergeFactor越大耗费内存越多,索引速度也会快些,但我的感觉太大譬如300,最后合并的时候还是很满。Batch indexing 应 MergeFactor>10

Incoming search terms for the article:MergeFactor (19)lucene 两两 合并 索引 (16)lucene mergeFactor (12)ramBufferSizeMB (2)lucene maxmergeDoc (2)

Lucene的检索优化(一)

 
 

Sent to you by Jeffye via Google Reader:

 
 

Lucene的检索优化(一)

via 笨笨的小田园 by 笨笨 on 8/14/08

ucene支持内存索引:这样的搜索比基于文件的I/O有数量级的速度提升。
http://www.onjava.com/lpt/a/3273

而尽可能减少IndexSearcher的创建和对搜索结果的前台的缓存也是必要的。

Lucene面向全文检索的优化在于首次索引检索后,并不把所有的记录(Document)具体内容读取出来,而是只将所有结果中匹配度最高的头
100条结果(TopDocs)的ID放到结果集缓存中并返回,这里可以比较一下数据库检索:如果是一个10,000条的数据库检索结果集,数据库是一定
要把所有记录内容都取得以后再开始返回给应用结果集的。所以即使检索匹配总数很多,Lucene的结果集占用的内存空间也不会很多。对于一般的模糊检索应
用是用不到这么多的结果的,头100条已经可以满足90%以上的检索需求。

如果首批缓存结果数用完后还要读取更后面的结果时Searcher会再次检索并生成一个上次的搜索缓存数大1倍的缓存,并再重新向后抓取。所以如果
构造一个Searcher去查1-120条结果,Searcher其实是进行了2次搜索过程:头100条取完后,缓存结果用完,Searcher重新检索
再构造一个200条的结果缓存,依此类推,400条缓存,800条缓存。由于每次Searcher对象消失后,这些缓存也访问那不到了,你有可能想将结果
记录缓存下来,缓存数尽量保证在100以下以充分利用首次的结果缓存,不让Lucene浪费多次检索,而且可以分级进行结果缓存。

Lucene的另外一个特点是在收集结果的过程中将匹配度低的结果自动过滤掉了。这也是和数据库应用需要将搜索的结果全部返回不同之处。

 
 

Things you can do from here:

Subscribe to 笨笨的小田园 using Google Reader
Get started using Google Reader to easily keep up with all your favorite sites

 
 
Incoming search terms for the article:lucene查询优化 (7)lucene 优化 (6)lucene优化 (6)lucene 查询优化 (4)lucene 缓存 (4)

Lucene的检索优化(二)–Hits的改进

 
 

Sent to you by Jeffye via Google Reader:

 
 

Lucene的检索优化(二)–Hits的改进

via 笨笨的小田园 by 笨笨 on 8/15/08

刚刚开始学Lucene,看的是Lucene in
Action。顺着看下去,很自然的就是使用Hits来访问Search的结果。但是使用起来,发现Search的速度是很快,不过如果结果很多的话(比如1W个),通过Hits访问所有的结果速度非常慢,就是简单地从每个结果中读一个Field,在我的机器上用了接近2分钟。因为我的应用索引的只是我的数据的两个域包含文本信息的域,我本希望通过Lucene查找出符合需求的数据ID,再通过ID去判断数据库中的其他域来决定最终的结果。这样连取ID就需要2分钟,我的应用可受不了。

第一个想到的方法是把我的全部数据域都做成Lucene的索引,然后全部通过Lucene去搜索。但是由于我的很多域是数字,全部转换成Lucene能接受的字符串,感觉性能不会好。另外如果我想针对搜索的结果做统计,也没法避免需要遍历全部的搜索结果,如果1W个结果就需要2分钟的话,就算不用处理其他的域,也是不能忍受的。

开源软件的好处就是可以读代码。通过阅读Hits的代码,终于找到了解决问题的办法。

Lucene
的代码看起来并不是特别Professional。比如下面这两个Hits的初始化函数。首先里面的q,s,f什么的让人看起来就不是太舒服(其他的代码里还用i,j做循环变量)。其次这两个函数只有o那一个赋值不一样,明显应该只写一个,让另一个来调用。最后程序里面直接用了50这个常数,编程的大忌。(50在其他函数里面也有)

Hits(Searcher s, Query q, Filter f) throws IOException {
    weight =
q.weight(s);
    searcher =
s;
    filter =
f;
    nDeletions =
countDeletions(s);
   
getMoreDocs(50); // retrieve 100 initially
   
lengthAtStart = length;
  }

  Hits(Searcher s, Query q, Filter f, Sort o)
throws IOException {
    weight =
q.weight(s);
    searcher =
s;
    filter =
f;
    sort =
o;
    [...]