Prácticas recomendadas para las consultas de grafos
Puedes optimizar el rendimiento de las consultas de BigQuery Graph estructurando tus consultas de Graph Query Language (GQL) para minimizar los datos analizados y los resultados intermedios.
Inicia el recorrido de la ruta desde los nodos de cardinalidad baja
Para mantener pequeños los conjuntos de resultados intermedios y acelerar la ejecución de las consultas, escribe tus
consultas de grafo de modo que el recorrido de la ruta comience desde nodos de cardinalidad más baja,
independientemente de la dirección del recorrido de la ruta. Las siguientes
sentencias MATCH usan filtros de propiedades para reducir la cantidad de posibles
nodos de inicio en lugar de calcular todas las coincidencias y, luego, filtrar:
MATCH (p:Person {id: 10})-[own:Owns]->(a:Account)
MATCH (a:Account WHERE balance > 10)<-[own:Owns]-(p:Person)
Esto es especialmente importante para las consultas de rutas cuantificadas:
MATCH (p:Person {id: 10})-[own:Owns]->{1,3}(a:Account)
Usa la sintaxis ANY o ANY SHORTEST para las verificaciones de conectividad
Las consultas de ruta cuantificadas pueden devolver rutas duplicadas entre los nodos de origen y
los nodos de destino. Si tu objetivo es verificar la conectividad y no necesitas
todas las rutas posibles, usa ANY o ANY SHORTEST para reducir los cálculos redundantes
y mejorar la eficiencia de la búsqueda de rutas. Por ejemplo, la siguiente
sentencia MATCH usa ANY SHORTEST para mantener solo una ruta de acceso entre cada par
de nodos:
MATCH ANY SHORTEST (a1:Account)-[t:Transfers]->{1,3}(a2:Account)
Usa el recorrido de ruta direccional
Los esquemas de BigQuery Graph son direccionales, lo que significa que cada
arista tiene un nodo de origen y un nodo de destino. Aunque la sintaxis de la consulta de grafo
permite el recorrido de rutas en cualquier dirección (por ejemplo, -[edge]-), recomendamos
usar el recorrido de rutas direccional (por ejemplo, -[edge]-> o
<-[edge]-) para obtener un mejor rendimiento. Cualquier recorrido de ruta de dirección puede causar
pérdida de rendimiento.
La siguiente sentencia MATCH usa el recorrido de ruta de cualquier dirección:
-- Avoid.
MATCH (a1:Account {id: 7})-[t:Transfers]-(a2:Account)
En su lugar, combina dos recorridos direccionales con UNION ALL:
MATCH (a1:Account {id: 7})-[t:Transfers]->(a2:Account)
...
UNION ALL
...
MATCH (a1:Account {id: 7})<-[t:Transfers]-(a2:Account)
Especifica etiquetas de forma explícita
Si se omiten las etiquetas de nodo o de borde en una consulta, BigQuery Graph enumera todas las etiquetas de nodo y de borde que cumplen con los requisitos. Esta enumeración puede hacer que se analicen más etiquetas de las necesarias. Para evitar esto, especifica etiquetas para todos los nodos y bordes de tu consulta siempre que sea posible.
Por ejemplo, en la siguiente consulta, se especifican las etiquetas Account y Transfers:
GRAPH graph_db.FinGraph
MATCH (a1:Account)-[t:Transfers]->(a2:Account)
RETURN COUNT(*) AS num_transfers;
Evita omitir etiquetas, ya que podría analizar otras relaciones innecesarias
entre nodos. En la siguiente consulta, a1 puede representar una cuenta o una
persona, y t puede representar una transferencia o la propiedad de una cuenta.
GRAPH graph_db.FinGraph
MATCH (a1)-[t]->(a2)
RETURN COUNT(*) AS num_transfers;
Prefiere una sola sentencia MATCH
BigQuery Graph te permite incluir varias declaraciones MATCH en
una sola consulta de grafo. Estas declaraciones están conectadas por variables declaradas varias veces
que representan el mismo nodo o borde. Sin embargo, usar varias instrucciones MATCH
puede disminuir los beneficios de cardinalidad en las instrucciones. Cuando
sea posible, usa una sola sentencia MATCH para obtener un mejor rendimiento.
Por ejemplo, las siguientes consultas son equivalentes, pero la primera tiene un mejor
rendimiento porque usa una sola sentencia MATCH:
-- Preferred syntax.
GRAPH graph_db.FinGraph
MATCH
(p:Person {id: 1})-[o:Owns]->
(a:Account)-[t:Transfers]->(a2:Account)
RETURN o.account_id, t.amount;
-- Avoid this syntax.
GRAPH graph_db.FinGraph
MATCH (p:Person {id: 1})-[o:Owns]->(a:Account)
MATCH (a:Account)-[t:Transfers]->(a2:Account)
RETURN o.account_id, t.amount;
Limita las aristas recorridas desde nodos de alta cardinalidad
Cuando consultas grafos, algunos nodos pueden tener una cantidad significativamente mayor de aristas entrantes o salientes en comparación con otros nodos. Estos nodos de alta cardinalidad a veces se denominan supernodos o nodos centrales. Los supernodos pueden causar problemas de rendimiento, ya que los recorridos a través de ellos pueden implicar el procesamiento de grandes cantidades de datos, lo que genera un sesgo de datos y tiempos de ejecución prolongados.
Para optimizar una consulta de un grafo con supernodos, usa la
función ROW_NUMBER()
dentro de una cláusula FILTER o WHERE en MATCH para limitar la
cantidad de aristas que la consulta recorre desde o hacia un nodo. Esta técnica es
especialmente útil cuando no necesitas una enumeración completa de todas
las conexiones desde o hacia un supernodo.
Por ejemplo, si algunas cuentas de FinGraph tienen una gran cantidad de
transacciones, puedes usar ROW_NUMBER() para limitar la cantidad de bordes de Transfers
que se deben considerar para cada Account y evitar una consulta ineficiente:
GRAPH graph_db.FinGraph
MATCH (a1:Account)-[e1:Transfers WHERE e1 IN {
GRAPH graph_db.FinGraph
-- Sample 5 edges per source node
MATCH -[selected_e:Transfers]->
FILTER ROW_NUMBER() OVER (
PARTITION BY SOURCE_NODE_ID(selected_e)) < 5
RETURN selected_e
}]->{1,3}(a2:Account)
RETURN COUNT(*) AS cnt;
Muestrea nodos o bordes intermedios en consultas de varios saltos
También puedes mejorar la eficiencia de las consultas con ROW_NUMBER() para muestrear
nodos intermedios en consultas de varios saltos. Esta técnica mejora la eficiencia, ya que limita la cantidad de rutas que la consulta considera para cada nodo intermedio. Para ello, divide una consulta de varios saltos en varias declaraciones MATCH
separadas por NEXT y aplica ROW_NUMBER() en el punto medio en el que necesites
tomar muestras:
GRAPH graph_db.FinGraph
MATCH (a1:Account)-[e1:Transfers]->(a2:Account)
-- Sample 5 destination nodes per a1 source node
FILTER ROW_NUMBER() OVER (PARTITION BY ELEMENT_ID(a1)) < 5
RETURN a1, a2
NEXT
MATCH (a2)-[e2:Transfers]->(a3:Account)
RETURN a1.id AS src_id, a2.id AS mid_id, a3.id AS dst_id;
¿Qué sigue?
- Para obtener más información sobre cómo escribir consultas de grafos, consulta la descripción general de las consultas.
- Obtén más información para diseñar tu esquema de grafo.