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