我有一个2亿+记录的数据集,我正在寻找一个专用的后端来为先进的解决方案提供支持。 Lucene因其受欢迎程度和许可类型而受到关注,但我也对其他开源建议持开放态度。我正在寻找建议,来自战壕的故事,甚至更好的直接指导我将需要的硬件和软件结构的数量。要求:
必须:
很高兴:
注意:
投票支持任何有用的信息,使我能够更接近企业级别类型提前解决方案
答案 0 :(得分:7)
如果每条记录相对较小(少于几个字),您可以尝试Trie数据结构:
http://en.wikipedia.org/wiki/Trie
它专为减轻快速前缀匹配而设计,相对空间有效。我已经将这个数据结构用于您正在寻找的确切自动完成功能,而且我知道其他人已经为大批量生产网站做过这样的事情。根据我的经验,您可以预期单个查询的响应时间为几十毫秒。
您可以很容易地自己实现Trie,或者可以下载实现。参见
Where do I find a standard Trie based map implementation in Java?
根据您使用的实现,使用相关性分数标记每个索引记录应该相对简单,然后您可以使用这些记录从查询中获取记录列表时进行排序。
答案 1 :(得分:4)
你可能不需要任何太花哨的东西。您的“必须”列表可以通过简单的数据库引擎(例如BerkeleyDB或ESENT)来满足。将所有单词放入表中,然后使用seek查找单词。
一个8kb页面的b树应至少获得250个字符串/页面,这将产生1M页面页面,从而得到高度为3的b树。即使使用5400 RPM笔记本电脑磁盘,I / O延迟也会减少超过15ms所以,在最坏的情况下,你将能够在最坏的情况下获得~50ms的结果(完全未缓存的数据和慢速驱动)。
(我构建了一个使用基于ESENT的PersistentDictionary类的预先输入应用程序。对于第一次查找,我得到了大约35毫秒的响应,其中数据根本没有缓存。在做了一堆查询后,响应时间下降到~5ms)。
要支持大量并发用户,您可以添加更多缓存或更快的磁盘。完全缓存所有数据可能是可能的(目前8GB的RAM是相当实惠的)并且先行数据肯定足够小以适应SSD,这将提供可笑的IOPS数量。我可能会选择SSD,因为即使缓存很冷(例如重启后),它也能提供出色的性能。
基于数据库引擎的解决方案应该非常快速地构建。
答案 2 :(得分:2)
以下是我们在SOLR中的表现:
搜索的关键是如何使用适当的过滤工厂获得正确的数据类型。
在架构中设置名为 textPrefix
的数据类型示例:
<!--
This type is used for type ahead style searching and starts with searching.
-->
−
<fieldType name="textPrefix" class="solr.TextField" positionIncrementGap="1" sortMissingLast="true">
−
<analyzer type="index">
<tokenizer class="solr.KeywordTokenizerFactory"/>
<filter class="ISOLatin1AccentFilterFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
<!-- Remove non alpha-numeric characters -->
<filter class="solr.PatternReplaceFilterFactory" pattern="[^a-zA-Z0-9 ]" replacement="" replace="all"/>
<filter class="solr.TrimFilterFactory"/>
<!-- Remove leading "the "-->
<filter class="solr.PatternReplaceFilterFactory" pattern="^the\s" replacement="" replace="all"/>
<filter class="solr.TrimFilterFactory"/>
<filter class="solr.EdgeNGramFilterFactory" minGramSize="1" maxGramSize="6"/>
</analyzer>
−
<analyzer type="query">
<tokenizer class="solr.KeywordTokenizerFactory"/>
<filter class="ISOLatin1AccentFilterFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
<!-- Remove non alpha-numeric characters -->
<filter class="solr.PatternReplaceFilterFactory" pattern="[^a-zA-Z0-9 ]" replacement="" replace="all"/>
<filter class="solr.TrimFilterFactory"/>
<!-- Remove leading "the "-->
<filter class="solr.PatternReplaceFilterFactory" pattern="^the\s" replacement="" replace="all"/>
<filter class="solr.TrimFilterFactory"/>
</analyzer>
</fieldType>
然后在您的架构文档中创建一个新的数据字段:
<field name="CustomerNamePrefix" type="textPrefix" indexed="true" stored="false"/>
然后将Customer Name的副本存储到此CustomerNamePrefix字段中。
现在,当您查询此字段时,您可以简单地使用名称的第一个字母,它将为您提供这些字母的最佳匹配。根据您的查询方式,您可以根据文档中的其他因素来提高结果。
示例:
http://solrserver:8080/solr/select/?q=CustomerNamePrefix:jame&q.alt=*:*&start=0&rows=10&mm=1