Best practice per le query Graph
Puoi ottimizzare le prestazioni delle query di BigQuery Graph strutturando le query Graph Query Language (GQL) in modo da ridurre al minimo i dati scansionati e i risultati intermedi.
Inizia l'esplorazione del percorso dai nodi con cardinalità bassa
Per mantenere ridotti i set di risultati intermedi e velocizzare l'esecuzione delle query, scrivi le query del grafo in modo che l'esplorazione del percorso inizi da nodi con cardinalità inferiore, indipendentemente dalla direzione dell'esplorazione del percorso. Le seguenti istruzioni MATCH utilizzano i filtri delle proprietà per ridurre il numero di possibili nodi di partenza anziché calcolare tutte le corrispondenze e poi filtrarle:
MATCH (p:Person {id: 10})-[own:Owns]->(a:Account)
MATCH (a:Account WHERE balance > 10)<-[own:Owns]-(p:Person)
Questo è particolarmente importante per le query di percorso quantificate:
MATCH (p:Person {id: 10})-[own:Owns]->{1,3}(a:Account)
Utilizza la sintassi ANY o ANY SHORTEST per i controlli di connettività
Le query di percorso quantificate possono restituire percorsi duplicati tra i nodi di origine e i nodi di destinazione. Se il tuo obiettivo è verificare la connettività e non hai bisogno di tutti i percorsi possibili, utilizza ANY o ANY SHORTEST per ridurre i calcoli ridondanti e migliorare l'efficienza della ricerca dei percorsi. Ad esempio, la seguente istruzione MATCH utilizza ANY SHORTEST per mantenere un solo percorso tra ogni coppia di nodi:
MATCH ANY SHORTEST (a1:Account)-[t:Transfers]->{1,3}(a2:Account)
Utilizza l'attraversamento del percorso direzionale
Gli schemi di BigQuery Graph sono direzionali, il che significa che ogni arco ha un nodo di origine e un nodo di destinazione. Sebbene la sintassi delle query dei grafi consenta l'esplorazione dei percorsi in qualsiasi direzione (ad esempio, -[edge]-), per ottenere prestazioni migliori consigliamo di utilizzare l'esplorazione dei percorsi direzionali (ad esempio, -[edge]-> o <-[edge]-). L'attraversamento del percorso in qualsiasi direzione potrebbe causare una perdita di prestazioni.
La seguente istruzione MATCH utilizza l'attraversamento del percorso in qualsiasi direzione:
-- Avoid.
MATCH (a1:Account {id: 7})-[t:Transfers]-(a2:Account)
Combina invece due attraversamenti direzionali con UNION ALL:
MATCH (a1:Account {id: 7})-[t:Transfers]->(a2:Account)
...
UNION ALL
...
MATCH (a1:Account {id: 7})<-[t:Transfers]-(a2:Account)
Specifica le etichette in modo esplicito
Se le etichette dei nodi o degli archi vengono omesse in una query, BigQuery Graph enumera tutte le etichette dei nodi e degli archi idonee. Questa enumerazione potrebbe comportare la scansione di più etichette del necessario. Per evitare questo problema, specifica le etichette per tutti i nodi e gli archi nella query, se possibile.
Ad esempio, la seguente query specifica le etichette Account e Transfers:
GRAPH graph_db.FinGraph
MATCH (a1:Account)-[t:Transfers]->(a2:Account)
RETURN COUNT(*) AS num_transfers;
Evita di omettere le etichette, perché potrebbero essere analizzate altre relazioni non necessarie tra i nodi. Nella seguente query, a1 può rappresentare un account o una persona, mentre t può rappresentare un trasferimento o la proprietà di un account.
GRAPH graph_db.FinGraph
MATCH (a1)-[t]->(a2)
RETURN COUNT(*) AS num_transfers;
Preferisci una singola istruzione MATCH
BigQuery Graph consente di includere più istruzioni MATCH in una singola query del grafo. Queste istruzioni sono collegate da variabili con più dichiarazioni che rappresentano lo stesso nodo o arco. Tuttavia, l'utilizzo di più istruzioni MATCH può ridurre i vantaggi della cardinalità tra le istruzioni. Quando
possibile, utilizza una singola istruzione MATCH per ottenere prestazioni migliori.
Ad esempio, le seguenti query sono equivalenti, ma la prima ha un rendimento migliore perché utilizza una singola istruzione 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 gli archi attraversati dai nodi ad alta cardinalità
Quando esegui query sui grafi, alcuni nodi possono avere un numero di archi in entrata o in uscita significativamente maggiore rispetto ad altri nodi. Questi nodi ad alta cardinalità vengono talvolta chiamati super nodi o nodi hub. I super nodi possono causare problemi di prestazioni perché gli attraversamenti attraverso di essi potrebbero comportare l'elaborazione di grandi quantità di dati, il che porta a una distorsione dei dati e a tempi di esecuzione lunghi.
Per ottimizzare una query di un grafo con supernodi, utilizza la
funzione ROW_NUMBER()
all'interno di una clausola FILTER o WHERE in MATCH per limitare il
numero di archi che la query attraversa da o verso un nodo. Questa tecnica è particolarmente utile quando non hai bisogno di un'enumerazione completa di tutte le connessioni da o verso un super nodo.
Ad esempio, se alcuni account in FinGraph hanno un numero elevato di transazioni, puoi utilizzare ROW_NUMBER() per limitare il numero di archi Transfers da considerare per ogni Account ed evitare una query inefficiente:
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;
Campiona nodi o archi intermedi nelle query multi-hop
Puoi anche migliorare l'efficienza delle query utilizzando ROW_NUMBER() per campionare i nodi intermedi nelle query multi-hop. Questa tecnica migliora l'efficienza limitando il numero di percorsi che la query considera per ogni nodo intermedio. Per farlo, suddividi una query multi-hop in più istruzioni MATCH separate da NEXT e applica ROW_NUMBER() nel punto intermedio in cui devi eseguire il campionamento:
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;
Passaggi successivi
- Per scoprire di più sulla scrittura di query del grafico, consulta la panoramica delle query.
- Scopri di più sulla progettazione dello schema del grafo.