Best practice per le query del grafico

Questo documento descrive le best practice per ottimizzare le query del grafico BigQuery.

Avviare l'attraversamento del percorso dai nodi a bassa cardinalità

Per mantenere piccoli i set di risultati intermedi e velocizzare l'esecuzione delle query, scrivi le query del grafo in modo che l'attraversamento del percorso inizi dai nodi a cardinalità inferiore, indipendentemente dalla direzione dell'attraversamento 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 filtrare:

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 del percorso quantificato:

MATCH (p:Person {id: 10})-[own:Owns]->{1,3}(a:Account)

Utilizzare la sintassi ANY o ANY SHORTEST per i controlli di connettività

Le query del percorso quantificato 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)

Utilizzare l'attraversamento del percorso direzionale

Gli schemi del grafico BigQuery sono direzionali, il che significa che ogni arco ha un nodo di origine e un nodo di destinazione. Sebbene la sintassi delle query del grafico consenta l'attraversamento del percorso in qualsiasi direzione (ad esempio, -[edge]-), ti consigliamo di utilizzare l'attraversamento del percorso direzionale (ad esempio, -[edge]-> o <-[edge]-) per prestazioni migliori. L'attraversamento del percorso in qualsiasi direzione potrebbe causare una perdita di prestazioni.

La seguente istruzione MATCH utilizza il path traversal in qualsiasi direzione:

-- Avoid.
MATCH (a1:Account {id: 7})-[t:Transfers]-(a2:Account)

In alternativa, combina 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)

Specificare le etichette in modo esplicito

Se le etichette dei nodi o degli archi vengono omesse in una query, il grafico BigQuery enumera tutte le etichette dei nodi e degli archi qualificati. 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é potrebbe eseguire la scansione di altre relazioni non necessarie tra i nodi. Nella seguente query, a1 può rappresentare un account o una persona e t può rappresentare un trasferimento o la proprietà di un account.

GRAPH graph_db.FinGraph
MATCH (a1)-[t]->(a2)
RETURN COUNT(*) AS num_transfers;

Preferire una singola istruzione MATCH

Il grafico BigQuery ti consente di includere più istruzioni MATCH in una singola query del grafico. Queste istruzioni sono collegate da variabili dichiarate più volte 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 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;

Limitare gli archi attraversati dai nodi a cardinalità elevata

Quando esegui query sui grafici, alcuni nodi possono avere un numero di archi in entrata o in uscita significativamente maggiore rispetto ad altri nodi. Questi nodi a cardinalità elevata vengono talvolta chiamati supernodi o nodi hub. I supernodi possono causare problemi di prestazioni perché gli attraversamenti 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 grafico con supernodi, utilizza la ROW_NUMBER() funzione all'interno di una FILTER clausola o WHERE clausola in MATCH per limitare il numero di archi che la query attraversa da o verso un nodo. Questa tecnica è particolarmente utile quando non è necessaria un'enumerazione completa di tutte le connessioni da o verso un supernodo.

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;

Eseguire il campionamento di 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