Solr:如何提高数值字段上特定值的过滤查询(而非范围查询)的性能?

3
我有一个包含大约6千万到1亿个文档的索引。我们几乎总是基于外键ID查询这些文档(除了其他过滤查询和字段查询等),以将查询范围限定在特定的父对象中。
例如:/solr/q=*:*&fq=parent_id_s:42 是的,这里的“_s”表示这是当前的solr.StrField字段类型。
我的问题是:我应该将其更改为TrieIntField吗?这样会加速性能吗?如果是的话,给定我知道我将始终查询单个特定值,并且该parent_id的基数处于10,000-100,000(最大)数量级,那么理想的precisionStep和positionIncrementGap值是什么?
附加细节编辑(来自下面答案的评论):
我们系统的使用方式是,我们最终会连续使用相同的fq进行许多查询。当缓存被填充时,系统运行得非常快。当由于提交而导致缓存被清空时,这个查询(甚至只有这个fq的测试用例)可能需要长达20秒。因此,我正在尝试找出如何加速填充缓存的初始查询。
第二次编辑:
很抱歉,经过进一步测试,发现上述性能差的情况只发生在返回facets字段时(例如,&facet=true&facet.field=resolved_facet_facet)。有大约十几个这些字段时,查询有时需要20-30秒,但只有在新的搜索器中才会出现这种情况。当缓存被填充时,它是瞬间完成的。因此,也许我的问题在于facets字段,而不是parent_id字段。

有很多想法。你有没有考虑使用SolrCloud对索引进行分片?这将有助于分担构建/维护过滤器缓存的负担。你提交的频率是多少?你在提交后预热缓存吗?你是否研究过其他分层搜索解决方案,如SirenDB? - Doug T.
(1) 我们有一位Solr教练,他根据经验建议将索引限制在大约1000万个文档以内。记住这个数字,你可以将索引分成10个分片。 (2) 另外一个问题,你考虑过使用SSD作为索引存储吗? - cheffe
回应您的第二次编辑:这些字段类型是哪个方面的字段?它们与普通字符串有什么不同吗?如果有,您能否发布来自schema.xml的字段类型定义? - cheffe
@ cheffe 好想法。我刚刚检查了模式,它们只是没有分析器的普通字符串(尽管它们是多值的)。其中一些是布尔值或“是”/“否”之类的东西,因此我将所有具有2-4个可能值的值都更改为在搜索器的默认参数中使用 facet.method = enum。似乎这是一个小的改进,但似乎打开并调整自动预热可能是我所能做的最好的事情... - Jeff Gran
3个回答

4

TrieIntField 是针对范围查询进行了优化的,如果你只搜索一个特定值,那么这个字段类型是最优的。

你看过自动预热查询吗?这些查询在创建新的 IndexSearcher 时运行(例如在启动时或索引提交时),以便一些缓存已经准备好。根据你的要求,你也可以设置 useColdSearcher 标志为 true,这样当缓存已经预热时,才会提供新的 Searcher。有关更多详细信息,请查看此处:https://cwiki.apache.org/confluence/display/solr/Query+Settings+in+SolrConfig#QuerySettingsinSolrConfig-Query-RelatedListeners


我认为你可能走在正确的轨道上。目前我没有使用任何自动预热功能。我的一个要求是,对于任何文档的添加或更新都必须立即生效。如果我使用自动预热,并保持“使用冷搜索器”的状态,那么这样做是否能够满足我的需求?旧的搜索器是否仍然会使用最新的软提交文档,直到新的搜索器被预热? - Jeff Gran
另外,请查看我对问题的第二次编辑:这是否也适用于facet缓存?我需要为哪种类型的查询自动预热缓存? - Jeff Gran
我相信当你关闭冷搜索器并引入自动预热时,会有一些延迟,但你可以进行实验以找到两者之间的良好平衡。此外,你可能想要启用缓存自动预热,特别是对于过滤器:(有关更多详细信息,请参见wiki.apache.org/solr/SolrCaching#autowarmCount) - spyk
关于您的第二次编辑,我认为您的情况类似于这个:http://stackoverflow.com/questions/21565988/solr-is-slow-at-first-facet-query-but-quite-fast-for-later-queries,该链接也指向了自动预热。 - spyk

2
看起来你可能没有从过滤器缓存结果集中获得太多好处。过滤器的一个更重要的特点是它们会缓存它们的结果集。这使得某个特定过滤器的第一次运行需要更长时间,因为需要建立缓存,但后续使用相同过滤器时速度会更快。
根据你所描述的基数,你可能只是在浪费资源,并且在没有任何用处的情况下污染了过滤器缓存。你可以像这样关闭过滤器查询的缓存:turn off caching
/solr/q=*:*&fq={!cache=false}parent_id_s:42

如果我理解正确的话,我认为parent_id并不是很多唯一的?如果是这样的话,缓存它是完全有意义的。考虑到索引的大小,我猜他有足够的内存可用。无论如何,@Jeff Gran,只要告诉我们你拥有的命中率(以及你现在正在缓存的过滤器数量)以获得更好的信息。 - Persimmonium
@femtoRgon 这是一个好想法,但不适用于我的情况。由于我们的系统使用方式,结果是我们会连续多次使用相同的fq进行查询。当缓存被填充时,系统运行非常快。但是,当由于提交而导致缓存被清空时,这个查询(即使只有这个fq的测试用例)可能需要长达20秒的时间。因此,我正在尝试找出如何加速填充缓存的初始查询。 - Jeff Gran

0

我认为过滤查询在这种情况下并没有帮助。

q=parent_id_s:42 是通过术语"parent_id_s:42"查询索引并获取一组文档ID。由于帖子(文档ID)是按术语索引的,并且假设您有足够的内存来保存此信息(无论是在JVM还是OS缓存中),那么此查找应该非常快速。

假设过滤器缓存已经预热并且您有100%的命中率,以下哪一个更快?

q=parent_id_s:42
fq=parent_id_s:42

我认为它们非常接近。但是我可能错了。有人知道吗?有人对此进行过性能测试吗?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接