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

Hus*_*man 3 database sql-server lucene indexing search-engine

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

  1. 标题
  2. 文件内容
  3. 日期从,日期到
  4. 从修改日期,到修改日期
  5. 所有者
  6. 地点
  7. 其他元数据

我正在使用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的效果如何?什么是替代解决方案?

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

Pet*_*ses 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 strings = <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. 您将拥有适当的工具来扩展/调整/备份/恢复搜索,而不会影响您的应用程序.