使用 Lucene 目录作为主要文件存储有哪些缺点?

What are the drawbacks of using a Lucene directory as a primary file store?

我想使用 Lucene MMapDirectory as a primary file store. Each file would be stored in a separate document as a byte array in a StoredField。所有应该可搜索的文件属性,如文件名、大小等,都将存储在同一文档的可索引字段中。

我的问题是:

  1. 使用 Lucene 目录存储文件有哪些缺点,尤其是在索引和搜索性能以及内存 (RAM) 消耗方面?
  2. 如果这不是 "no-go",是否有 better/faster 将文件存储在目录中而不是字节数组的方法?

所以您不会使用 MMapDirectory,而是实际的 lucene 索引。

我在使用 Lucene 作为一些项目的主要数据存储方面取得了很好的经验。

请确保还包含一个 generated/natural 唯一 ID,因为文档 ID 不是固定的或可靠的。

还要确保您使用适合您的用例的目录实现。我已经在低负载情况下切换到普通的 RandomAccess 实现,因为它使用更少的内存并且几乎一样快。

简答

我真的很喜欢 Luсene 并认为它是最好的开源库,但我担心将它用作主要文件源不是一个好的决定,原因是:

  • 高CPU/memory开销
  • 慢 index/query 性能
  • 高 HDD 利用率和双倍索引大小
  • 恢复能力弱

长答案

在幕后,lucene 使用以下文件将所有存储的字段保存在一个段中:

  • 字段索引文件 (.fdx),
  • 字段数据文件 (.fdt)。

您可以在 Lucene50StoredFieldsFormat’s 文档中阅读有关其工作原理的更多信息。

  1. 这意味着如果出现任何 I/O 问题,几乎不可能恢复任何文件。
  2. 为了return一个文件-lucene必须以逐块的方式从光盘中读取和解压缩二进制数据。这意味着高 CPU 解压缩开销和高内存占用以将整个文件保存在 java 堆 space 中。与文件和网络存储相比,也没有流式传输。
  3. 最大文档大小受编解码器实施的限制 - 每个文档 2 GB
  4. Lucene 具有独特的一次写入分段架构:最近索引的文档被写入一个新的独立段,以仅附加、一次写入的方式:一旦写入,这些段文件将永远不会再更改。当过多的 RAM 被用于保存最近索引的文档时,或者当您要求 Lucene 刷新您的搜索器以便您可以搜索所有最近索引的文档时,就会发生这种情况。随着时间的推移,较小的段被合并成较大的段,索引在任何时候都具有活动段文件的对数 "staircase" 结构。这种架构成为文件存储的一个大问题:
    • 您不能删除文件 - 只能标记为不可用
    • 合并操作需要 2x 光盘 space 并消耗大量资源和光盘吞吐量 - 它创建新的 .fdt 文件并通过 java 代码和 [=57 复制其他 .fdt 文件的内容=]堆内存