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

时间:2015-08-05 12:33:45

标签: sql-server database indexing lucene search-engine

我正在使用.Net开发一个高级搜索引擎,用户可以根据以下几个字段构建查询:

  1. 标题
  2. 文件内容
  3. 日期自,日期
  4. 从修改日期,到修改日期
  5. 所有者
  6. 位置
  7. 其他元数据
  8. 我正在使用lucene索引文档内容及其相应的ID。但是,其他元数据驻留在MS SQL DB中(以避免扩大索引,并在元数据的任何修改上不断更新索引)。

    我如何进行搜索?

    当任何用户搜索词语时:

    • 通过在SQL DB中查找,根据用户选择的条件缩小搜索结果。
    • 将匹配的ID返回给lucene搜索器Web服务,该服务搜索从Adv Search Web服务返回的DocumnentID中输入的关键字。
    • 然后再次查看数据库,获取文档ID的相关元数据(从lucence返回)。

    如您所见,在DB中有一个查找,然后是Lucene和Finally DB,以获取要在Grid中显示的值。

    问题:

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

    另一个问题是将ID传递给lucene Search Service,传递数十万个ID的效果如何?什么是替代解决方案?

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

1 个答案:

答案 0 :(得分:7)

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

1)通过MS-SQL缩小搜索空间

  • 在您的应用中生成查询
  • 通过网络发送到MS-SQL
  • 解析/优化/执行SQL查询
  • [!!]返回100,000个ID的I / O开销

2)通过Lucene.NET执行有界全文搜索

  • [!!]在应用程序中生成/执行包含100,000个ID子句的大型BooleanQuery的Lucene内存开销(您需要首先覆盖1024个子句的默认限制,以便测量此效果)
  • 标准Lucene全文搜索执行
  • 返回匹配ID

3)通过MS-SQL实现结果细节

  • 快速,索引,基于ID的搜索结果文档查找(仅显示结果的第一页所需的通常约10-25条记录)

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

A)索引所有元数据(日期,作者,位置等)将无法接受地增加索引的大小。

  • 首先尝试一下:这是最佳做法,除了文本搜索之外,让Lucene为您完成所有过滤,您将大大减少查询执行开销。

  • 此外,索引的大小主要与每个字段的基数有关。例如,如果您只有500个唯一所有者名称,则只存储500个字符串,每个lucene文档将通过符号表查找在内部引用其所有者(4字节整数* 2MM docs + 500字符串 =< 8MB额外)。

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

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

总结一下最佳做法:

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

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

  • 返回ID

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

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

  1. 您不必担心搜索索引内存要求会蚕食应用程序内存要求。
  2. 您将利用复杂的过滤器缓存性能提升和基于操作系统的I / O优化。
  3. 您将能够轻松地从广泛使用/支持的基于配置的环境中迭代您的搜索解决方案。
  4. 您可以使用工具来扩展/调整/备份/恢复搜索,而不会影响您的应用程序。