这个指导有点误导。它更复杂,很难尝试编写一套适合所有情况的规则。随着数据的变化,规则也会发生变化。随着查询和过滤器类型的改变,规则也会改变。特定过滤器的执行速度可能比广泛的过滤器慢,规则会发生变化。在每个段的基础上,过滤器的结果大小可能与另一个段相反,它并不总是可预测的。 所以首先你必须了解更多的内部结构,然后你需要在进入现代 Elasticsearch 2.x 时放弃试图控制它。
注意: 您的第二个报价(过滤顺序)和相关链接指向的页面对于 Elasticsearch 2.x 而言被视为“过时”,稍后会更新。因此,这些建议可能适用于现代,也可能不适用于现代。
及时回顾 Elasticsearch 1.x 以及订购建议的原因:
让我们先谈谈过滤器在内存中是如何表示的。它们要么是匹配文档的迭代列表,要么是随机访问“它在这里”模型。取决于过滤器的类型,取决于哪个更有效。现在,如果所有内容都被缓存,那么您只是将它们相交,并且成本会因大小和类型而异。
如果过滤器未缓存,但可缓存,则过滤器将独立执行,之前的过滤器仅会通过交集的总成本影响它。
如果过滤器不可缓存,那么它可以由以前的结果指导。想象一个Query 加上一个Filter。如果您执行查询,并在应用过滤器之后,如果过滤器限制为非常小的记录集,您将做很多额外的工作。您在收集、评分和整体构建大量结果方面浪费了时间。但是,如果您转换为FilteredQuery 并同时执行这两项操作,那么Query 将忽略所有已被Filter 消除的记录。它只需要考虑已经在使用的相同文件。这称为“跳过”。并非所有过滤器类型都利用跳过,但有些可以。这就是为什么较小的“引导”过滤器会使其他人更快地使用它。
除非您了解每种过滤器类型、数据的启发式方法以及每个特定过滤器将如何受到这些过滤器的影响,否则您没有足够的信息来说明“将最受限制的过滤器放在首位,和更大的第二个”,希望它能成功。对于bool,默认情况下不缓存其整体结果,因此您必须注意其重复性能(和/或缓存它)。当过滤器交叉点的一侧较小时,效率更高。因此,从一个小的开始会使所有其他交叉口更快,因为它们只能变得更小。如果是 bool query 而不是 filter 进行评分,那么避免对更多文档进行评分就更重要了。
另一个重要的注意事项是“最具体的过滤器优先”有时可能会很慢(脚本过滤器或其他),所以它应该真正阅读:“最低成本,最具体的过滤器第一个”。
与Elasticsearch 2.0, things will change:
是时候忘记您对查询和过滤器的所有了解了:Elasticsearch 2.0 将自行做出更好的决策,而不是依赖用户来制定优化的查询。
在 2.x 中,您应该减少对系统的博弈,让引擎做出最佳选择。引擎实际上可能最终会在引擎盖下产生完全不同的东西,重写过滤器,内部结构和数据的彻底改变。而且您甚至可能不再控制缓存。因此,您需要阅读更多相关信息。
之前的过滤器 API 可以通过两种方式使用:或者使用匹配文档的迭代器,或者使用允许检查特定文档是否匹配过滤器的可选随机访问 API。到目前为止一切都很好,除了使用过滤器的最佳方式取决于您拥有哪种过滤器:例如,script 过滤器在使用随机访问 API 时更有效,而bool 过滤器更有效使用迭代器 API。这对优化来说简直是一场噩梦,这也是为什么一方面 bool 过滤器与另一方面 and 和 or 过滤器表现不同的根本原因。
引擎现在将考虑更多因素来决定什么是最好的,包括评分、结果大小的估计、与相关过滤器相交的最佳方法,甚至可能基于每个段等等。
此外,这篇文章清楚地表明,即使缓存也可能会产生误导,它并不总是能让事情变得更快。有时内部数据结构在最初使用时比始终缓存的位集结构更好。因此,在 2.x 中,这也在发生变化,以避免缓存从本机数据结构中执行得更好的东西,而无需缓存。
在博文Roaring Bitmaps中有更多详细信息:
显然,最重要的要求是快速:如果缓存的过滤器比再次执行过滤器慢,它不仅会消耗内存,还会使查询变慢。编码越复杂,就越有可能因为 CPU 使用率增加而减慢编码和解码速度
在这里,您可以获得大量关于内部数据结构、缓存、交集等 2.x 内部变化的信息,这将帮助您更深入地了解过滤器性能。
如果您不熟悉搜索引擎内部结构,您可能会感到惊讶,但搜索引擎最重要的组成部分之一是能够有效地压缩和快速解码已排序的整数列表。
从最近的几个 2.x 博客链接中,您对您的问题有很多背景知识,它们讨论了您尝试使用过滤器排序解决的所有问题。信息和细节都在那里,您可以更好地了解 1.x 与 2.x 以及如何解决查询+过滤器。所以请记住:
没有任何特定的实现总是比所有其他的都好。
另请参阅这些 1.x 资源以获取历史参考: