`
longgangbai
  • 浏览: 7272673 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

搜索引擎 luence的使用和优化

阅读更多

无论是不是reopen,optimize都会耗用更多的space来存储临时文件.但这些都是临时文件,在动作结束后会被释放掉.所以如果硬盘空间足够,这些多余的耗用应该不是大问题。

但我的index目录总共有3G(我把旧的document删除了)。不过每次optimize一样要花费很长时间。我不知道应该如何重新设置document的id.我的lucene version是2.0的。

lucene的optimize的结果除了将index的文件数变成3个,还有什么好处呢?到现在我看来只有在delete索引节点后有必要通过optimize真正的把这些节点删除,其他的优势似乎非常不明显。(因为我每次写入index的索引内容都是新的,不会有重复或追加现象)。我现在彻底把optimize从程序里去掉了,运行到现在已经1个月了,每分钟都有新内容加进去,但index目录依然很正常,文件数24个,从文件的修改时间上来看也很正常。search动作也很正常。

如果一次optimize需要花费5分钟以上的时间,而这个操作又是不可中断的,一旦在optimize过程中终止了程序,就会出现lucene自身无法恢复问题。这样对于程序要求太高了。对于服务器管理也要求太高了。

=========================================
上面的内容有些多, 不过也对大家有益. 他说最后他把执行优化的代码去掉了,运行很好. 对于大数据量的来说, 这是个经验. 除非采用冗余的机制, 而不能对正在使用的数据进行优化操作. 会造成用户访问阻塞.

由上面可见的, 我就不说了.
13, 索引过程中的任意时刻、任意进程都能对索引文件进行优化,而且这样做也不会损坏索引文件或使其不能被搜索,但是在索引过程中对索引进行优化的做法并不值得提倡。优化操作的最佳时机是在索引过程结束之后,且当你确认在此后的一段时间内不会对索引文件进行更改的时候。在索引过程中进行优化只会使优化操作耗费更多的时间。(请大家汲取这个思想)



14, 还是优化, 些人问: 我用lucene做了一个Search Engine
程序运行也很正常,但如果连续运行几个月,有时会出现磁盘空间不足的情况 .
通过iw.addDocument(doc)写入index
当list里的东西全部被写入完毕后,通过optimze来优化索引,
可这个东西运行不是很稳定,有的时候很正常,运行几个月都okay,有时1个月就出现问题了。会在index的目录里出现很多文件。这些文件似乎是应该被optimize掉的。 一个索引只能有一个indexreader, 在optimize的时候可以有多个indexsearcher在工作。
你得确保
-->optimize确实调用了
-->optimize的时候, 得有双倍的磁盘空间. 可见优化的代价.



15 ,面的lucene都是在一个目录里面的, 大家也都看到了. 也就是如果这个文件一直很大怎么办. 首先碰到的第一个问题是就是文件大小限制. 首先面临的是一个大目录问题.

16, lucene的性能测试:
下面给出一些测试数据,如果你觉得可以接受,那么可以选择。
测试一:250万记录,300M左右文本,生成索引380M左右,800线程下平均处理时间300ms。
测试二:37000记录,索引数据库中的两个varchar字段,索引文件2.6M,800线程下平均处理时间1.5ms。


17 . 分布搜索

我们可以使用 MultiReader 或 MultiSearcher 搜索多个索引库。

MultiReader reader = new MultiReader(new IndexReader[] { IndexReader.Open(@"c:\index"), IndexReader.Open(@"\\server\index") });
IndexSearcher searcher = new IndexSearcher(reader);
Hits hits = searcher.Search(query);



IndexSearcher searcher1 = new IndexSearcher(reader1);
IndexSearcher searcher2 = new IndexSearcher(reader2);
MultiSearcher searcher = new MultiSearcher(new Searchable[] { searcher1, searcher2 });
Hits hits = searcher.Search(query);

还可以使用 ParallelMultiSearcher 进行多线程并行搜索。

18. 合并索引库

将 directory1 合并到 directory2 中。
Directory directory1 = FSDirectory.GetDirectory("index1", false);
Directory directory2 = FSDirectory.GetDirectory("index2", false);

IndexWriter writer = new IndexWriter(directory2, analyzer, false);
writer.AddIndexes(new Directory[] { directory });
Console.WriteLine(writer.DocCount());
writer.Close();

19. 显示搜索语法字符串

我们组合了很多种搜索条件,或许想看看与其对等的搜索语法串是什么样的。
BooleanQuery query = new BooleanQuery();
query.Add(query1, true, false);
query.Add(query2, true, false);
//...

Console.WriteLine("Syntax: {0}", query.ToString());

输出:
Syntax: +(name:name* value:name*) +number:[0000000000000000b TO 0000000000000000d]

呵呵,就这么简单。

20. 操作索引库

删除 (软删除,仅添加了删除标记。调用 IndexWriter.Optimize() 后真正删除。)
IndexReader reader = IndexReader.Open(directory);

// 删除指定序号(DocId)的 Document。
reader.Delete(123);

// 删除包含指定 Term 的 Document。
reader.Delete(new Term(FieldValue, "Hello"));

// 恢复软删除。
reader.UndeleteAll();

reader.Close();

增量更新 (只需将 create 参数设为 false,即可往现有索引库添加新数据。)
Directory directory = FSDirectory.GetDirectory("index", false);
IndexWriter writer = new IndexWriter(directory, analyzer, false);
writer.AddDocument(doc1);
writer.AddDocument(doc2);
writer.Optimize();
writer.Close();

21. 优化

批量向 FSDirectory 增加索引时,增大合并因子(mergeFactor )和最小文档合并数(minMergeDocs)有助于提高性能,减少索引时间。

IndexWriter writer = new IndexWriter(directory, analyzer, true);

writer.maxFieldLength = 1000; // 字段最大长度
writer.mergeFactor = 1000;
writer.minMergeDocs = 1000;

for (int i = 0; i < 10000; i++)
{
// Add Documentes...
}

writer.Optimize();
writer.Close();

相关参数说明


转自《深入 Lucene 索引机制》

利用 Lucene,在创建索引的工程中你可以充分利用机器的硬件资源来提高索引的效率。当你需要索引大量的文件时,你会注意到索引过程的瓶颈是在往磁盘上写索引文件的过程中。为了解决这个问题, Lucene 在内存中持有一块缓冲区。但我们如何控制 Lucene 的缓冲区呢?幸运的是,Lucene 的类 IndexWriter 提供了三个参数用来调整缓冲区的大小以及往磁盘上写索引文件的频率。

22.合并因子 (mergeFactor)

这个参数决定了在 Lucene 的一个索引块中可以存放多少文档以及把磁盘上的索引块合并成一个大的索引块的频率。比如,如果合并因子的值是 10,那么当内存中的文档数达到 10 的时候所有的文档都必须写到磁盘上的一个新的索引块中。并且,如果磁盘上的索引块的隔数达到 10 的话,这 10 个索引块会被合并成一个新的索引块。这个参数的默认值是 10,如果需要索引的文档数非常多的话这个值将是非常不合适的。对批处理的索引来讲,为这个参数赋一个比较大的值会得到比较好的索引效果。

23.最小合并文档数 (minMergeDocs)

这个参数也会影响索引的性能。它决定了内存中的文档数至少达到多少才能将它们写回磁盘。这个参数的默认值是10,如果你有足够的内存,那么将这个值尽量设的比较大一些将会显著的提高索引性能。

24.最大合并文档数 (maxMergeDocs)

这个参数决定了一个索引块中的最大的文档数。它的默认值是 Integer.MAX_VALUE,将这个参数设置为比较大的值可以提高索引效率和检索速度,由于该参数的默认值是整型的最大值,所以我们一般不需要改动这个参数。

25 , 根据官方文档:从中可以分析出,如果在optimize索引的时候,也同时使用Searcher。索引空间的使用情况如下:
1. 原始索引
2. 由IndexWriter使用的索引,用于optimize
3. 由IndexSearcher使用的索引,用于搜索。

所以要三倍的正常空间.

为什么需要优化?
尽管未经优化的索引在大多数应用程序中都能够很好地进行工作,但在那些处理大批量索引的应用程序中,使用优化过的索引会给应用程序带来更多的好处。特别是在搜索操作需要长时间打开多个索引文件的情况下,更能体现出索引被优化后的优势,因为使用优化过的索引可以减少需要打开的文件描述符的个数

优化所需的磁盘空间
值得指出的是,Lucene对一个索引的优化操作是通过把已存在的段合并成一个全新的段来完成的,这些已存在段的内容最终会在新的段中表示出来。因而在进行优化时,使用的磁盘空间会有明显的增加。在新段创建完成时,Lucene删除并移除这些旧段。因此,在旧的段还没有被删除之前,索引占用的磁盘空间会变成原来的两倍,因为此时新段和旧段都会存储在索引中。在优化完成后,所占用的磁盘空间会降回到优化前的状态。请记住,索引优化的对象可以是多文件索引或复合索引。



26 , 索引文件有大小限制吗?(翻译)

某些 32 位操作系统限制每个文件不能大于 2GB。

解决方法:
1. 使用 IndexWriter.setMaxMergeDocs() 减小 MaxMergeDocs 数值。
2. 使用多个索引库。使用复合索引.


27, IndexWriter.SetUseCompoundFile(true) 有什么用?

在创建索引库时,会合并多个 Segments 文件到一个 .cfs 中。此方式有助于减少索引文件数量,减少同时打开的文件数量。原因:
某些操作系统会限制同时打开的文件数量。

解决方法:
1. 使用 IndexWriter's setUseCompoundFile(true) 创建复合文件,减少索引文件数量。
2. 不要将 IndexWriter's mergeFactor 的值设置过大。尽管这能加快索引速度,但会增加同时打开的文件数量。
3. 如果在搜索时发生该错误,那么你最好调用 IndexWriter.Optimize() 优化你的索引库。
4. 确认你仅创建了一个 IndexSearcher 实例,并且在所有的搜索线程中共用。(原文:"Make sure you only open one IndexSearcher, and share it among all of the threads that are doing searches -- this is safe, and it will minimize the number of files that are open concurently. " 晕~~~,究竟要怎么做? )

28, 为什么搜索不到结果?(翻译)

可能原因:
. 搜索字段没有被索引。
. 索引库中的字段没有分词存储,无法和搜索词语进行局部匹配。
. 搜索字段不存在。
. 搜索字段名错误,注意字段名称区分大小写。建议对字段名进行常量定义。
. 要搜索的词语是忽略词(StopWords)。
. 索引(IndexWriter)和搜索(IndexSearcher)所使用的 Analyzer 不同。
. 你所使用的 Analyzer 区分大小写。比如它使用了 LowerCaseFilter,而你输入的查询词和目标大小写不同。
. 你索引的文档(Document)太大。Lucene 为避免造成内存不足(OutOfMemory),缺省仅索引前10000个词语(Term)。可以使用 IndexWriter.setMaxFieldLength() 调整。
. 确认在搜索前,目标文档已经被添加到索引库。
. 如果你使用了 QueryParser,它可能并没有按照你所设想的去分析 BooleanQuerySyntax。

如果还不行,那么:

. 使用 Query.ToString() 查看究竟搜索了些什么。
. 使用 Luke 看看你的索引库究竟有什么。

29, 上面的luke是查看索引库的, 我下载了一个版本, 居然总提示我给他的索引路径不对.无奈. .

30 ,

QueryParser 是线程安全的吗?

不是。

31, 说说分布式数据存储. 支持lucene的分布式搜索就是 hadoop. 这个也是apache下的属于lucene的开源项目. 但目前的我看只支持linux的分布机器. 网上很多这个方面的. 据说开发hadoop的人已经去了yahoo. 让hadoop支撑雅虎的分布式搜索. 所以按说功能强大.2006年的一月份Nutch和Lucene的缔造者Doug Cutting加入了Yahoo公司,从那时起,Yahoo就开始进行Hadoop的部署与研究. 但网上有人说, 这个分布式效率不高.

参数如下:

经测试,Hadoop并不是万用灵丹,很取决于文件的大小和数量,处理的复杂度以及群集机器的数量,相连的带宽,当以上四者并不大时,hadoop优势并不明显。
比如,不用hadoop用java写的简单grep函数处理100M的log文件只要4秒,用了hadoop local的方式运行是14秒,用了hadoop单机集群的方式是30秒,用双机集群10M网口的话更慢,慢到不好意思说出来的地步。

评: 怎么评价上面的哥们测试结果呢. 但愿他说的不对. 因为如果这样, yahoo不就死了..

32, MaxDoc() 和 DocCount()、NumDocs() 有什么不同?

MaxDocs() 表示索引库中最大的 Document ID 号,由于中间的某些 Document 可能被删除,因此不能使用 MaxDocs() 来表示 Document 数量。IndexWriter.DocCount()、IndexReader.NumDocs()、IndexSearcher.Reader.NumDocs() 都表示索引库中 Document 数量。

33, 为什么同时进行搜索和更新会引发 FileNotFoundException 异常?(翻译)

可能原因:
1. 某个搜索或更新对象禁用了锁。
2. 搜索和更新使用了不同的 lockDir。
3. 索引库被存放在 NFS (or Samba) 文件系统上。

尽管搜索是只读操作,但 IndexSeacher 为了获取索引文件列表,也必须打开时锁定索引库。如果锁没有正确设置,那么它将取回一个错误的文件列表(此时 IndexWriter 可能正在添加或优化索引),从而导致该异常发生。

34, write.lock 有什么用?哪些类会用到它?(翻译)

write.lock 用来协调索引库的并发修改处理。
当 IndexWriter 打开索引库,或者 IndexReader 删除文档时都将创建该锁。

35. commit.lock 文件有什么用?哪些类会用到它?(翻译)

commit.lock 在调整索引库 segments 文件内容时使用。 IndexReader 和 IndexWriter 都会使用到它。

36, 如何更新已经索引的文档? (翻译)

你只能先删除,然后添加更新后的文档。

使用 IndexWriter.addIndexes(IndexReader[]) 和 IndexWriter.addIndexes(Directory[]) 合并索引库有什么不同? (翻译)

使用 Directory[] 参数所需的文件句柄和内存较小,索引文件仅需打开一次,而使用 IndexReader[] 参数则需要打开所有的索引库。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics