Почему neo4j предупреждает: "Этот запрос строит декартово произведение между несвязанными образцами"?

Я определяю отношения между двумя сущностями, Джином и Хромосомой, и думаю, что это простой и нормальный способ после импорта данных из CSV:

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

Тем не менее, когда я это делаю, neo4j (пользовательский интерфейс браузера) жалуется:

Этот запрос строит декартово произведение между несвязанными образцами. Если часть запроса содержит несколько отключенных шаблонов, это создаст декартово произведение между всеми этими частями. Это может привести к большому объему данных и замедлить обработку запросов. Несмотря на то, что он иногда предназначен, часто может быть возможно переформулировать запрос, который позволяет избежать использования этого перекрестного продукта, возможно, путем добавления взаимосвязи между различными частями или с помощью ДОПОЛНИТЕЛЬНОГО МАТЧА (идентификатор: (с)).

Я не понимаю, в чем проблема. chromosomeID - это очень простой внешний ключ.

2 ответа

Решение

Браузер говорит вам, что:

  1. Он обрабатывает ваш запрос, сравнивая каждый Gene экземпляр и каждый Chromosome пример. Если ваша БД имеет G гены и C хромосомы, то сложность запроса O(GC), Например, если мы работаем с геномом человека, существует 46 хромосом и, возможно, 25000 генов, поэтому БД должен будет сделать 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);
    

    Он использует WITH пункт, чтобы заставить первый MATCH пункт, чтобы выполнить в первую очередь, избегая декартово произведение. Второй MATCH (а также WHERE) предложение использует результаты первого MATCH пункт и индекс, чтобы быстро получить точные гены, которые принадлежат каждой хромосоме.

Как Logisima упоминает в комментариях, это всего лишь предупреждение. Соответствие декартовому произведению происходит медленно. В вашем случае все должно быть в порядке, так как вы хотите подключиться ранее не подключенным Gene а также Chromosome узлы и вы знаете размер декартового произведения. Существует не слишком много хромосом и небольшое количество генов. Если бы вы MATCH например, гены на белках, запрос может взорвать.

Я думаю, что предупреждение предназначено для других проблемных запросов:

  • если ты MATCH декартово произведение, но вы не знаете, есть ли отношения, которые вы могли бы использовать OPTIONAL MATCH
  • если хотите MATCH оба Gene и Chromosome без каких-либо отношений, вы должны разделить запрос

В случае, если ваш запрос занимает слишком много времени или не завершается, вот еще один вопрос, дающий несколько советов, как оптимизировать декартовы продукты: Как оптимизировать запросы Neo4j Cypher с множественными совпадениями узлов (декартовой продукт)

Другие вопросы по тегам