我有一个相当大的集合(~10MM元素),我需要运行返回相当大的结果集(~500K元素)的查询。我需要这些元素按照两个属性分组或排序:
A
)有大约2MM个不同的实例。B
)有大约10个不同的实例。需要将具有匹配(A, B)
对的所有元素组合在一起以进行处理。我可能会将它们添加到地图中然后处理地图;但是,鉴于我需要并行运行相当多的查询,我宁愿避免创建中间映射,而是直接从结果集中提取/处理组。
执行此操作的一种方法是按(A, B)
排序;这是有效的,因为我可以从结果集中提取属于一起的块,并在我去的时候处理它们。但是,查询执行时间太慢。我尝试向A
和B
添加不同类型的索引,但似乎没有任何帮助提高性能。为了记录,我不需要他们排序;我只需要匹配的(A, B)
元素一起显示在结果集中。
有没有办法实现这个目标?任何帮助表示赞赏。
答案 0 :(得分:1)
可能有几种方法可以优化它。
在CQEngine中,我倾向于使用术语排序来描述所需的结果,然后可以有多种排序策略来实现排序。
CQEngine中的默认行为是使用所谓的 materialize 排序策略,该策略涉及将与查询匹配的所有结果复制到临时集合中,然后将其显式排序。这不适用于大型ResultSet,因此在这种情况下,对于500K元素的ResultSet来说,这并不奇怪。有关详细信息,请参阅OrderingStrategies。
然而TL; DR是:您可以请求CQEngine使用索引排序策略。
属性A的索引加速排序
在您的示例中,您需要按(A,B)排序结果,因此您可以请求CQEngine使用属性A上的索引来加速排序。由于您需要按A然后按B进行排序,这不会完全消除排序结果的需要,因为如果引擎找到多个与索引A中单个存储桶中共存的查询匹配的对象,它仍然必须按属性B对该桶中的少量匹配对象进行显式排序,以便通过(A,B)实现整体排序。
所有其他条件相同,基于10MM元素的集合大小和A的2MM不同值,您可以预期A上的索引中的每个桶包含5个对象。所以我希望这种方法可以大大缩短首次结果延迟时间。虽然可能不完美......
部分索引
上述方法通常适用于类似于时间序列的数据,其中A可能是时间戳,并且您希望搜索最近的项目,并且您希望按新近度订购结果。
然而,使用属性A上的索引来驱动搜索与时间序列不相似的工作负载的缺点是,正在遍历以实现结果排序的A上的有序索引可能是污染,其中包含许多与您尝试加速的查询不匹配的对象。所以这可以引入过滤开销。
您没有多提及您的疑问。例如,您是否提前知道了一组查询,还是完全是任意的?
我问这个问题,因为如果你事先知道了你期望的查询(或者至少是你提前预期的一些查询片段),那么你可以在属性A上设置PartialIndex es您希望在工作负载中找到过滤器查询。
部分索引(加上启用索引排序策略)可以是缓解索引污染的好方法,这意味着索引可用于加速大型ResultSet的排序,而且不会容易过度过滤。希望有所帮助!