Best Practices für Graphabfragen
Sie können die Abfrageleistung von BigQuery Graph optimieren, indem Sie Ihre GQL-Abfragen (Graph Query Language) so strukturieren, dass die gescannten Daten und Zwischenergebnisse minimiert werden.
Pfaddurchlauf von Knoten mit niedriger Kardinalität starten
Damit die Zwischenergebnissätze klein bleiben und die Abfrageausführung beschleunigt wird, sollten Sie Ihre Graphabfragen so schreiben, dass die Pfaddurchquerung bei Knoten mit niedrigerer Kardinalität beginnt, unabhängig von der Richtung der Pfaddurchquerung. In den folgenden MATCH-Anweisungen werden Attributfilter verwendet, um die Anzahl der möglichen Startknoten zu reduzieren, anstatt alle Übereinstimmungen zu berechnen und dann zu filtern:
MATCH (p:Person {id: 10})-[own:Owns]->(a:Account)
MATCH (a:Account WHERE balance > 10)<-[own:Owns]-(p:Person)
Dies ist besonders wichtig für quantifizierte Pfadabfragen:
MATCH (p:Person {id: 10})-[own:Owns]->{1,3}(a:Account)
ANY- oder ANY SHORTEST-Syntax für Konnektivitätsprüfungen verwenden
Quantifizierte Pfadabfragen können doppelte Pfade zwischen Quell- und Zielknoten zurückgeben. Wenn Sie die Verbindung prüfen möchten und nicht alle möglichen Pfade benötigen, verwenden Sie ANY oder ANY SHORTEST, um redundante Berechnungen zu reduzieren und die Effizienz der Pfadsuche zu verbessern. In der folgenden MATCH-Anweisung wird beispielsweise ANY SHORTEST verwendet, um nur einen Pfad zwischen jedem Knotenpaar beizubehalten:
MATCH ANY SHORTEST (a1:Account)-[t:Transfers]->{1,3}(a2:Account)
Richtungsabhängige Pfaddurchquerung verwenden
BigQuery Graph-Schemas sind gerichtet, d. h., jede Kante hat einen Quellknoten und einen Zielknoten. Obwohl die Syntax für Graphabfragen die Pfaddurchquerung in jede Richtung zulässt (z. B. -[edge]-), empfehlen wir die Verwendung der gerichteten Pfaddurchquerung (z. B. -[edge]-> oder <-[edge]-), um die Leistung zu verbessern. Das Durchlaufen von Pfaden in beliebiger Richtung kann zu Leistungseinbußen führen.
In der folgenden MATCH-Anweisung wird die Pfaddurchquerung in beliebiger Richtung verwendet:
-- Avoid.
MATCH (a1:Account {id: 7})-[t:Transfers]-(a2:Account)
Kombinieren Sie stattdessen zwei gerichtete Durchläufe mit UNION ALL:
MATCH (a1:Account {id: 7})-[t:Transfers]->(a2:Account)
...
UNION ALL
...
MATCH (a1:Account {id: 7})<-[t:Transfers]-(a2:Account)
Labels explizit angeben
Wenn Knoten- oder Kantenlabels in einer Abfrage weggelassen werden, listet BigQuery Graph alle infrage kommenden Knoten- und Kantenlabels auf. Diese Aufzählung kann dazu führen, dass mehr Labels als nötig gescannt werden. Um dies zu vermeiden, geben Sie nach Möglichkeit Labels für alle Knoten und Kanten in Ihrer Abfrage an.
In der folgenden Abfrage werden beispielsweise die Labels Account und Transfers angegeben:
GRAPH graph_db.FinGraph
MATCH (a1:Account)-[t:Transfers]->(a2:Account)
RETURN COUNT(*) AS num_transfers;
Vermeiden Sie das Weglassen von Labels, da sonst möglicherweise andere, nicht benötigte Beziehungen zwischen Knoten gescannt werden. In der folgenden Abfrage kann a1 ein Konto oder eine Person und t eine Übertragung oder eine Kontoinhaberschaft darstellen.
GRAPH graph_db.FinGraph
MATCH (a1)-[t]->(a2)
RETURN COUNT(*) AS num_transfers;
Einzelne MATCH-Anweisung bevorzugen
Mit BigQuery Graph können Sie mehrere MATCH-Anweisungen in eine einzelne Graphabfrage einfügen. Diese Anweisungen sind durch mehrfach deklarierte Variablen verbunden, die denselben Knoten oder dieselbe Kante darstellen. Die Verwendung mehrerer MATCH-Anweisungen kann jedoch die Vorteile der Kardinalität über Anweisungen hinweg verringern. Verwenden Sie nach Möglichkeit eine einzelne MATCH-Anweisung, um die Leistung zu verbessern.
Die folgenden Abfragen sind beispielsweise äquivalent, aber die erste ist leistungsfähiger, da sie eine einzelne MATCH-Anweisung verwendet:
-- 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;
Durchlaufene Kanten von Knoten mit hoher Kardinalität begrenzen
Wenn Sie Diagramme abfragen, können einige Knoten im Vergleich zu anderen Knoten eine deutlich größere Anzahl eingehender oder ausgehender Kanten haben. Diese Knoten mit hoher Kardinalität werden manchmal als Superknoten oder Hub-Knoten bezeichnet. Superknoten können Leistungsprobleme verursachen, da bei Durchläufen durch sie große Datenmengen verarbeitet werden müssen, was zu Datenverzerrungen und langen Ausführungszeiten führt.
Wenn Sie eine Abfrage eines Graphen mit Superknoten optimieren möchten, verwenden Sie die Funktion ROW_NUMBER() in einer FILTER- oder WHERE-Klausel in MATCH, um die Anzahl der Kanten zu begrenzen, die die Abfrage von oder zu einem Knoten durchläuft. Diese Methode ist besonders nützlich, wenn Sie keine vollständige Aufzählung aller Verbindungen von oder zu einem Superknoten benötigen.
Wenn beispielsweise einige Konten in FinGraph eine große Anzahl von Transaktionen haben, können Sie mit ROW_NUMBER() die Anzahl der Transfers-Kanten begrenzen, die für jede Account berücksichtigt werden sollen, und so eine ineffiziente Abfrage vermeiden:
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;
Stichproben von Zwischenknoten oder -kanten in Multi-Hop-Abfragen
Sie können die Abfrageeffizienz auch verbessern, indem Sie mit ROW_NUMBER() Zwischenknoten in Multi-Hop-Abfragen abfragen. Diese Technik verbessert die Effizienz, da die Anzahl der Pfade, die die Abfrage für jeden Zwischenknoten berücksichtigt, begrenzt wird. Teilen Sie dazu eine Multi-Hop-Abfrage in mehrere MATCH-Anweisungen auf, die durch NEXT getrennt sind, und wenden Sie ROW_NUMBER() am Mittelpunkt an, an dem Sie eine Stichprobe erstellen müssen:
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;
Nächste Schritte
- Weitere Informationen zum Schreiben von Graphabfragen finden Sie in der Abfrageübersicht.
- Weitere Informationen zum Entwerfen eines Graphschemas