结合 DB 和 Lucene 搜索的最佳实践

Best Practice to Combine both DB and Lucene Search

我正在使用 .Net 开发高级搜索引擎,用户可以在其中基于多个字段构建查询:

  1. 标题
  2. 文档内容
  3. 开始日期,结束日期
  4. 从修改日期到修改日期
  5. 所有者
  6. 位置
  7. 其他元数据

我正在使用 lucene 来索引文档内容及其对应的 ID。但是,其他元数据驻留在 MS SQL DB 中(以避免扩大索引,并在元数据发生任何修改时不断更新索引)。

如何执行搜索?

当任何用户搜索某个词时:

正如您在这里注意到的那样,在 DB 中有一个查找,然后是 Lucene,最后是 DB 以获取要在 Grid 中显示的值。

问题:

如何克服这种情况?我想开始搜索 lucene,但如果索引的文档达到 200 万,这就有一个缺点。 (我认为首先使用数据库缩小结果对性能有很大影响)。

另一个问题是将 ID 传递给 lucene 搜索服务,传递数十万个 ID 的效率如何?替代解决方案是什么?

我欢迎任何想法,所以请分享您的想法。

您当前的解决方案在查询时会产生以下开销:

1) 通过 MS-SQL

缩小搜索 space
  • 正在您的应用中生成查询
  • 通过网络将其发送到 MS-SQL
  • Parsing/Optimizing/Execution SQL 个查询
  • [!!] I/O 返回 100,000 个 ID 的开销

2) 通过Lucene.NET

执行有界全文搜索
  • [!!] generating/executing 大型 BooleanQuery 的 Lucene 内存开销在应用程序中包含 100,000 个 ID 子句(您需要首先覆盖默认限制1024 个条款甚至可以衡量这种效果)
  • 标准 Lucene 全文搜索执行
  • Return匹配 ID

3) 通过 MS-SQL

实现结果细节
  • 搜索结果文档的快速、索引、基于 ID 的查找(只需要显示结果的第一页通常大约 10-25 条记录)

您可能做出的两个假设值得重新考虑

A) 索引所有元数据(日期、作者、位置等...)将不可接受地增加索引的大小。

  • 首先尝试一下:这是最佳实践,通过让 Lucene 执行所有过滤,您将大大减少查询执行开销你除了文字搜索。

  • 此外,索引的大小主要与每个字段的基数有关。例如,如果您只有 500 个唯一的所有者名称,那么只会存储这 500 个字符串,并且每个 lucene 文档将通过符号-table 查找(4 字节整数 * 2MM 文档 + 500字符串 = < 8MB 额外)。

B) MS-SQL 查询将是过滤非文本元数据的最快方式。

  • 重新考虑: 使用适当的 Lucene 类型正确索引元数据后,与查询 MS-SQL 相比,查询 Lucene 不会产生任何额外开销。 (在某些情况下,Lucene 甚至可能更快。)
  • 你的里程可能会有所不同,但根据我的经验,这种类型的过滤全文搜索在 2MM 文档的 Lucene 集合上执行时通常 运行 不到 100 毫秒。

总结最佳实践:

  • 索引所有您要查询或筛选的数据。 (无需存储源数据,因为 MS-SQL 是您的记录系统)。

  • 运行 针对 Lucene 的过滤查询(例如文本和日期范围、所有者、位置等...)

  • Return ID

  • 使用返回的 ID 从 MS-SQL 实现文档。


我还建议探索迁移到独立搜索服务器(Solr 或 Elasticsearch)的原因有很多:

  1. 您不必担心搜索索引内存需求会蚕食应用程序内存需求。
  2. 您将利用复杂的过滤器缓存性能提升和基于 OS 的 I/O 优化。
  3. 您将能够从广泛 used/supported.
  4. 的主要基于配置的环境中轻松地迭代您的搜索解决方案
  5. 您将拥有适当的工具来 scale/tune/backup/restore 搜索而不影响您的应用程序。