web-dev-qa-db-ja.com

neo4jが「このクエリは切断されたパターン間でデカルト積を構築する」と警告するのはなぜですか?

CSVからデータをインポートした後、GeneとChromosomeという2つのエンティティ間の関係を、シンプルで通常の方法で定義しています。

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

しかし、私がそうするとき、neo4j(ブラウザUI)は不平を言います:

このクエリは、切断されたパターン間のデカルト積を構築します。クエリの一部に複数の切断されたパターンが含まれている場合、これらのすべての部分間にデカルト積が構築されます。これにより、大量のデータが生成され、クエリ処理が遅くなる可能性があります。意図されることもありますが、おそらく異なるパーツ間の関係を追加するか、OPTIONAL MATCH(識別子は:(c))を使用することにより、このクロス積の使用を回避するクエリを再定式化できる場合があります。

問題が何であるかわかりません。染色体IDは非常に単純な外部キーです。

24
Sam Hokin

ブラウザは次のように言っています:

  1. すべてのGeneインスタンスとすべてのChromosomeインスタンスを比較してクエリを処理しています。 DBにG遺伝子とC染色体がある場合、クエリの複雑さはO(GC)です。たとえば、ヒトゲノムを扱っている場合、46の染色体とおそらく25000の遺伝子があるため、DBは_1150000_の比較を行う必要があります。
  2. クエリを変更することで、複雑さ(およびパフォーマンス)を改善できる可能性があります。たとえば、 created a index on :Gene(chromosomeID)を実行し、クエリを変更して、最初にカーディナリティが最小のノード(46染色体)のみに一致するようにした場合、 do O(G)(または_25000_)の「比較」-そして、それらの比較は実際には迅速なインデックス検索になります!これは、はるかに高速なアプローチです。

    インデックスを作成したら、次のクエリを使用できます。

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

    WITH句を使用して、最初のMATCH句を強制的に最初に実行し、デカルト積を回避します。 2番目のMATCH(およびWHERE)句は、最初のMATCH句の結果とインデックスを使用して、各染色体に属する正確な遺伝子をすばやく取得します。

36
cybersam

Logisimaがコメントで言及しているように、これは単なる警告です。デカルト積のマッチングは遅いです。以前は接続されていなかったGeneおよびChromosomeノードを接続する必要があり、デカルト積のサイズがわかっているため、この場合は問題ありません。染色体が多すぎず、遺伝子の数が少ない。 MATCHの場合、たとえばクエリが吹き飛ばす可能性のあるタンパク質上の遺伝子。

警告は他の問題のあるクエリを対象としていると思います。

  • MATCHデカルト積であるが、関係があるかどうかわからない場合は、OPTIONAL MATCHを使用できます
  • 関係なしでMATCHGeneChromosomeの両方を使用したい場合は、クエリを分割する必要があります

クエリに時間がかかりすぎるか終了しない場合は、デカルト積を最適化する方法のヒントを示す別の質問があります。 複数のノードが一致するNeo4j Cypherクエリを最適化する方法(デカルト積)

4
Martin Preusse