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

时间:2015-10-26 18:08:33

标签: neo4j cypher

在从CSV导入数据后,我认为两种实体Gene和Chromosome之间的关系,我认为这是简单而正常的方式:

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

然而,当我这样做时,neo4j(浏览器用户界面)抱怨道:

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

我不知道问题所在。 chromosomeID是一个非常简单的外键。

2 个答案:

答案 0 :(得分:34)

浏览器告诉你:

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

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

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

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

答案 1 :(得分:4)

正如logisima在评论中提到的那样,这只是一个警告。匹配笛卡尔积很慢。在您的情况下,它应该没问题,因为您想要连接以前未连接的InlineFormsetGene节点,并且您知道笛卡尔积的大小。没有太多的染色体和少量的基因。如果您Chromosome,查询可能会破坏蛋白质上的基因。

我认为该警告旨在用于其他有问题的查询:

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

如果您的查询花费的时间过长或未完成,这是另一个问题,提供了一些如何优化笛卡尔积的提示:How to optimize Neo4j Cypher queries with multiple node matches (Cartesian Product)