为什么neo4j警告:"此查询在断开连接的模式之间构建笛卡尔积"?

Sam*_*kin 24 neo4j cypher

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

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

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

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

我不明白这是什么问题.chromosomeID是一个非常简单的外键.

cyb*_*sam 35

浏览器告诉你:

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

    创建索引后,我们可以使用此查询:

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

    它使用一个WITH子句来强制第一个MATCH子句先执行,避免使用笛卡尔积.第二个MATCH(和WHERE)子句使用第一个MATCH子句和索引的结果快速获得属于每个染色体的确切基因.

  • 记录下来,这是解决方案,并大大加快了查询速度。我猜我对像PostgreSQL这样的数据库中的自动查询优化感到迷恋;看起来在neo4j中需要更加小心。 (2认同)

Mar*_*sse 6

正如 logisima 在评论中提到的,这只是一个警告。匹配笛卡尔积很慢。在你的情况下,由于要连接以前未连接的应该是OKGeneChromosome节点,你知道的乘积的大小。没有太多的染色体和少量的基因。如果您想MATCH例如蛋白质上的基因,查询可能会失败。

我认为警告是针对其他有问题的查询:

  • 如果您MATCH是笛卡尔积,但您不知道是否存在可以使用的关系OPTIONAL MATCH
  • 如果你想要MATCHaGene和 aChromosome没有任何关系,你应该拆分查询

如果您的查询花费太长时间或未完成,这里有另一个问题给出了一些如何优化笛卡尔积的提示:如何优化具有多个节点匹配的 Neo4j Cypher 查询(笛卡尔积)