sheet - ¿Por qué advierte neo4j: "Esta consulta crea un producto cartesiano entre patrones desconectados"?
neo4j enterprise (2)
Como logisima menciona en los comentarios, esto es solo una advertencia.
Hacer coincidir un producto cartesiano es lento.
En su caso, debería estar bien, ya que desea conectar nodos de
Chromosome
y
Gene
previamente desconectados y conoce el tamaño del producto cartesiano.
No hay demasiados cromosomas y una pequeña cantidad de genes.
Si usted
MATCH
por ejemplo, genes en proteínas, la consulta podría explotar.
Creo que la advertencia está destinada a otras consultas problemáticas:
-
si
MATCH
un producto cartesiano pero no sabes si existe una relación, podrías usarOPTIONAL MATCH
-
si desea
MATCH
tanto unGene
como unChromosome
sin ninguna relación, debe dividir la consulta
En caso de que su consulta tarde demasiado o no termine, aquí hay otra pregunta que da algunos consejos sobre cómo optimizar los productos cartesianos: Cómo optimizar las consultas Neo4j Cypher con coincidencias de múltiples nodos (Producto cartesiano)
Estoy definiendo la relación entre dos entidades, Gene y Cromosoma, en lo que creo que es la forma simple y normal, después de importar los datos de CSV:
MATCH (g:Gene),(c:Chromosome)
WHERE g.chromosomeID = c.chromosomeID
CREATE (g)-[:PART_OF]->(c);
Sin embargo, cuando lo hago, neo4j (interfaz de usuario del navegador) se queja:
Esta consulta crea un producto cartesiano entre patrones desconectados. Si una parte de una consulta contiene múltiples patrones desconectados, esto generará un producto cartesiano entre todas esas partes. Esto puede producir una gran cantidad de datos y ralentizar el procesamiento de consultas. Si bien ocasionalmente se pretende, a menudo es posible reformular la consulta que evita el uso de este producto cruzado, quizás agregando una relación entre las diferentes partes o utilizando OPCIONAL MATCH (el identificador es: (c)).
No veo cuál es el problema. chromosomeID es una clave externa muy sencilla.
El navegador te dice que:
-
Está manejando su consulta haciendo una comparación entre cada instancia de
Gene
y cada instancia deChromosome
. Si su DB tiene genesG
y cromosomasC
, entonces la complejidad de la consulta esO(GC)
. Por ejemplo, si estamos trabajando con el genoma humano, hay 46 cromosomas y quizás 25000 genes, por lo que el DB tendría que hacer1150000
comparaciones. -
Es posible que pueda mejorar la complejidad (y el rendimiento) modificando su consulta. Por ejemplo, si creamos un índice en
:Gene(chromosomeID)
, y modificamos la consulta para que coincidamos inicialmente en el nodo con la cardinalidad más pequeña (los 46 cromosomas), solo haríamosO(G)
(o25000
) "comparaciones" - ¡y esas comparaciones en realidad serían búsquedas rápidas de índices! Este enfoque debería ser mucho más rápido.Una vez que hemos creado el índice, podemos usar esta consulta:
MATCH (c:Chromosome) WITH c MATCH (g:Gene) WHERE g.chromosomeID = c.chromosomeID CREATE (g)-[:PART_OF]->(c);
Utiliza una cláusula
WITH
para forzar la ejecución de la primera cláusulaMATCH
, evitando el producto cartesiano. La segunda cláusulaMATCH
(yWHERE
) utiliza los resultados de la primera cláusulaMATCH
y el índice para obtener rápidamente los genes exactos que pertenecen a cada cromosoma.