Почему neo4j предупреждает: "Этот запрос строит декартово произведение между несвязанными образцами"?
Я определяю отношения между двумя сущностями, Джином и Хромосомой, и думаю, что это простой и нормальный способ после импорта данных из CSV:
MATCH (g:Gene),(c:Chromosome)
WHERE g.chromosomeID = c.chromosomeID
CREATE (g)-[:PART_OF]->(c);
Тем не менее, когда я это делаю, neo4j (пользовательский интерфейс браузера) жалуется:
Этот запрос строит декартово произведение между несвязанными образцами. Если часть запроса содержит несколько отключенных шаблонов, это создаст декартово произведение между всеми этими частями. Это может привести к большому объему данных и замедлить обработку запросов. Несмотря на то, что он иногда предназначен, часто может быть возможно переформулировать запрос, который позволяет избежать использования этого перекрестного продукта, возможно, путем добавления взаимосвязи между различными частями или с помощью ДОПОЛНИТЕЛЬНОГО МАТЧА (идентификатор: (с)).
Я не понимаю, в чем проблема. chromosomeID - это очень простой внешний ключ.
2 ответа
Браузер говорит вам, что:
- Он обрабатывает ваш запрос, сравнивая каждый
Gene
экземпляр и каждыйChromosome
пример. Если ваша БД имеетG
гены иC
хромосомы, то сложность запросаO(GC)
, Например, если мы работаем с геномом человека, существует 46 хромосом и, возможно, 25000 генов, поэтому БД должен будет сделать1150000
сравнения. Вы можете улучшить сложность (и производительность), изменив свой запрос. Например, если мы создали индекс на
: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 с множественными совпадениями узлов (декартовой продукт)