有人可以为我演示一种比我目前使用的更有效的笛卡尔积算法(假设有一个)。我环顾四周,用谷歌搜索了一下,但看不到任何明显的东西,所以我可能会遗漏一些东西。
foreach (int i in is) {
foreach (int j in js) {
//Pair i and j
}
}
这是我在代码中所做的高度简化的版本。这两个整数是用于检索一个/多个对象的查找键,并且来自两个查找的所有对象都配对在一起成为新对象。
在一个更大更复杂的系统中的这个小代码块成为一个主要的性能瓶颈,因为它在规模上运行的数据集。通过改进用于存储对象的数据结构和所涉及的查找,其中一些可能会得到缓解,但我认为主要问题仍然是笛卡尔积本身的计算。
编辑
因此,有关我对该算法的具体用法的更多背景信息,看看是否有任何技巧可以用来回应 Marc 的评论。整个系统是一个 SPARQL 查询引擎,它处理对图数据集的 SPARQL 查询,SPARQL 是一种基于模式的语言,因此每个查询都包含一系列与图匹配的模式。在两个后续模式没有公共变量(它们是不相交的)的情况下,有必要计算两个模式产生的解决方案的笛卡尔积,以获得整个查询的可能解决方案集。可能有任意数量的模式,我可能必须多次计算笛卡尔积,如果查询由一系列不相交的模式组成,这可能导致可能的解决方案出现相当指数的扩展。
不知何故,从现有的答案中,我怀疑是否有任何技巧可以适用
更新
所以我想我会发布我实施的更新,以尽量减少对笛卡尔积的需求,从而优化查询引擎。请注意,并非总是可以完全消除对产品的需求,但几乎总是可以进行优化,因此要连接的两个集合的大小要小得多。
由于作为一组三重模式的每个 BGP(基本图模式)都作为一个块(本质上)执行,因此引擎可以自由地在 BGP 中重新排序模式以获得最佳性能。例如,考虑以下 BGP:
?a :someProperty ?b .
?c :anotherProperty ?d .
?b a :Class .
按原样执行查询需要笛卡尔积,因为第一个模式的结果与第二个模式不相交,因此前两个模式的结果是它们各自结果的笛卡尔积。这个结果将包含比我们实际需要的更多的结果,因为第三个模式限制了第一个模式的可能结果,但是我们直到之后才应用这个限制。但是如果我们像这样重新排序:
?b a :Class .
?a :someProperty ?b .
?c :anotherProperty ?d .
我们仍然需要笛卡尔积来获得最终结果,因为第 2 和第 3 模式仍然不相交,但是通过重新排序,我们限制了第 2 模式结果的大小,这意味着我们的笛卡尔积的大小会小得多。
我们还进行了一些其他优化,但我不打算在这里发布它们,因为它开始对 SPARQL 引擎内部进行相当详细的讨论。如果有人对更多细节感兴趣,请发表评论或给我发推文@RobVesse