为什么neo4j会发出警告:“此查询在断开的模式之间构建笛卡尔积”?

xqk2d5yq  于 2023-08-04  发布在  其他
关注(0)|答案(3)|浏览(224)

在从CSV导入数据后,我以我认为简单而正常的方式定义了两个实体Gene和Chromosome之间的关系:

MATCH (g:Gene),(c:Chromosome)
WHERE g.chromosomeID = c.chromosomeID
CREATE (g)-[:PART_OF]->(c);

字符串
然而,当我这样做时,neo4j(浏览器UI)抱怨说:

  • 此查询在断开的模式之间构建笛卡尔积。如果查询的一部分包含多个断开连接的模式,这将在所有这些部分之间构建笛卡尔积。这可能会产生大量的数据并减慢查询处理。虽然偶尔是有意的,但通常可以重新制定避免使用此叉积的查询,可能是通过在不同部分之间添加关系或通过使用OPTIONAL MATCH(标识符为:(c))*

我看不出有什么问题。chromosomeID是一个非常简单的外键。

guykilcj

guykilcj1#

浏览器告诉你:
1.它通过在每个Gene示例和每个Chromosome示例之间进行比较来处理您的查询。如果你的数据库有G基因和C染色体,那么查询的复杂度是O(GC)。例如,如果我们正在研究人类基因组,有46条染色体,可能有25000个基因,所以数据库必须进行1150000比较。
1.您可以通过更改查询来提高复杂性(和性能)。例如,如果我们在:Gene(chromosomeID)上创建一个索引,并更改查询,使我们最初只匹配基数最小的节点(46条染色体),我们将只进行O(G)(或25000)“比较”--这些比较实际上是快速索引查找!这种方法应该快得多。
一旦我们创建了索引,我们就可以使用这个查询:

MATCH (c:Chromosome)
WITH c
MATCH (g:Gene) 
WHERE g.chromosomeID = c.chromosomeID
CREATE (g)-[:PART_OF]->(c);

字符串
它使用WITH子句强制第一个MATCH子句首先执行,从而避免笛卡尔积。第二个MATCH(和WHERE)子句使用第一个MATCH子句的结果和索引来快速获得属于每个染色体的确切基因。
[更新]
在最初编写这个答案时,WITH子句很有帮助。新版本的neo4j(如4.0.3)中的Cypher规划器现在生成相同的计划,即使省略了WITH,也没有创建笛卡尔积。您可以始终PROFILE查询的两个版本,以查看使用/不使用WITH的效果。

b5lpy0ml

b5lpy0ml2#

正如logisima在评论中提到的,这只是一个警告。匹配笛卡尔积很慢。在你的例子中,应该没问题,因为你想连接之前没有连接的GeneChromosome节点,并且你知道笛卡尔积的大小。没有太多的染色体和少量的基因。如果你想MATCH例如基因在蛋白质上的位置可能会被发现。
我认为这个警告是针对其他有问题的查询:

  • 如果你MATCH一个笛卡尔积,但你不知道是否有关系,你可以使用OPTIONAL MATCH
  • 如果你想同时MATCHGeneChromosome没有任何关系,你应该分开查询

如果你的查询时间太长或没有完成,这里有另一个问题,给出了一些如何优化笛卡尔积的提示:How to optimize Neo4j Cypher queries with multiple node matches (Cartesian Product)

bnl4lu3b

bnl4lu3b3#

当我基于如下值显式匹配时,我也会收到同样的抱怨:

MATCH (car :AUTOS {NAME: '2020 Dodge Charger SE')},
      (type :CARTYPES {NAME: 'MUSCLE CAR')}
CREATE (car)-[:'Is a Type of']-> (type)

字符串
我有一个节点AUTOS,其中有一个条目用于该汽车,节点CARTYPES,其中有一个条目用于该类型。
它仍然抱怨笛卡尔积。

相关问题