Bewährte Methoden für die Leistung für Apache AGE: Indizierung, AGE EXPLAIN und Datenlade-Benchmarks für Azure HorizonDB (Vorschau)

Apache AGE unterstützt von Azure HorizonDB, bietet Unterstützung für die erweiterte Graphverarbeitung und -abfrage. Das Erreichen einer optimalen Abfrageleistung erfordert jedoch eine durchdachte Strategie zum Indizieren und Laden von Daten. In diesem Leitfaden werden einige bewährte Methoden beschrieben, die auf aktuellen Benchmarkergebnissen und technischen Erkenntnissen basieren.

Index im Apache AGE

Die Indizierung ist entscheidend für die Verbesserung der Abfrageleistung, insbesondere in Graphdatenbanken.

Standardverhalten

Standardmäßig erstellt Apache AGE keine Indizes für neu erstellte Diagramme. Dies erfordert die explizite Erstellung von Indizes basierend auf der Art Ihrer Abfragen und Datensätze.

WHERE-Klausel

In Apache AGE werden die folgenden Abfragen unterschiedlich ausgewertet:

SELECT * FROM cypher('graph_name',
 $$
 MATCH (n:Customer {Name:'Alice'}) RETURN n
 $$)
AS (n agtype);
SELECT * FROM cypher('graph_name',
 $$
 MATCH (n:Customer) WHERE n.Name='Alice' RETURN n
 $$)
AS (n agtype);

Um die Indizierung vollständig nutzen zu können, müssen Sie verstehen, welche Arten von Indizes von Abfragen mit und ohne WHERE-Klausel verwendet werden.

EXPLAIN in Apache AGE

Im Gegensatz zu Standard-SQL erfordert das EXPLAIN-Schlüsselwort in Cypher-Abfragen ein anderes Abfrageformat.

SELECT * FROM cypher('graph_name',
 $$
 EXPLAIN
 MATCH (n:Customer)
 WHERE n.Name='Alice'
 RETURN n
 $$)
AS (plan text);
QUERY PLAN
--------------------------------------------------------------------------------------------------------------
Seq Scan on "Customer" n (cost=0.00..418.51 rows=43 width=32)
Filter: (agtype_access_operator(VARIADIC ARRAY[properties, '"Name"'::agtype]) = '"Alice"'::agtype)

So zeigen Sie die Unterschiede von Abfrageplänen ohne WHERE-Klausel an:

SELECT * FROM cypher('graph_name',
 $$
 MATCH (n:Customer {Name:'Alice'}) RETURN n
 $$)
AS (n agtype);
QUERY PLAN
---------------------------------------------------------------
Seq Scan on "Customer" n (cost=0.00..396.56 rows=9 width=32)
Filter: (properties @> '{"Name": "Alice"}'::agtype)

Allgemeine Indextypen

  • BTREE Index: Effektiv für genaue Übereinstimmungen und Bereichsabfragen. Empfohlen für die Verwendung mit Spalten wie ID, start_id und end_id in Edge- und Vertextabellen.
  • GIN Index: Nützlich für JSON-Felder, wodurch effiziente Suchvorgänge für Schlüsselwertpaare in der Eigenschaftenspalte ermöglicht werden.

Verwenden Sie die folgenden Befehle, um Indizes für Vertex- und Randtabellen zu erstellen:

  • Vertextabelle:

    CREATE INDEX ON graph_name."VLABEL" USING BTREE (id);
    CREATE INDEX ON graph_name."VLABEL" USING GIN (properties);
    
  • Randtabelle:

    CREATE INDEX ON graph_name."ELABEL" USING BTREE (id);
    CREATE INDEX ON graph_name."ELABEL" USING GIN (properties);
    
    CREATE INDEX ON graph_name."ELABEL" USING BTREE (start_id);
    CREATE INDEX ON graph_name."ELABEL" USING BTREE (end_id);
    

Indizierung eines bestimmten Schlüsselwerts in Eigenschaften

Für gezielte Abfragen kann ein kleinerer, effizienterer BTREE-Index für bestimmte Schlüssel in der Eigenschaftenspalte erstellt werden:

CREATE INDEX ON graph_name.label_name USING BTREE (agtype_access_operator(VARIADIC ARRAY[properties, '"KeyName"'::agtype]));

Bei diesem Ansatz wird die Indizierung unnötiger Daten vermieden und die Effizienz verbessert.

Abfrageplanerkenntnisse mit EXPLAIN

Das SCHLÜSSELwort EXPLAIN zeigt, wie Abfragen Indizes verwenden. Nicht alle Abfragen verwenden automatisch Indizes, insbesondere diejenigen, die ohne EINE WHERE-Klausel ausgestellt wurden. Verwenden Sie EXPLAIN, um die Indexverwendung zu überprüfen und Abfragen entsprechend zu optimieren.

Benchmark-Beobachtungen

Aktuelle Tests heben die Auswirkungen der Indizierung auf die Abfrageleistung hervor.

Indizierte und nicht indizierte Abfragen

In diesem Abschnitt werden die Leistungsunterschiede zwischen indizierten und nicht indizierten Abfragen erläutert.

  • Sequenzielle Scans übertreffen Index-Scans bei Abfragen, die ganze Tabellen abrufen.
  • Die Indizierung verbessert die Leistung von Join-Abfragen erheblich (z. B. bei der Ermittlung von Beziehungsanzahlen).

Bewährte Methoden zum Laden von Daten

Effizientes Laden von Daten ist für große Datasets von entscheidender Bedeutung.

Die AGEFreighter-Bibliothek bietet einen optimierten Prozess für die Datenaufnahme.

Laden von Daten mit AGEFreighter

AGEFreighter ist eine Python-Bibliothek, die das Laden von Daten in Apache AGE erleichtert. Es unterstützt verschiedene Datenformate, einschließlich CSV, Avro und Parkett, und bietet eine einfache Schnittstelle zum Laden von Daten in AGE-Diagramme.

Umgebungskonfiguration

  • Erstellen Sie eine Azure HorizonDB-Instanz mit aktiviertem AGE.
  • Python-Abhängigkeitsverwaltungstool wie Poesie wird empfohlen. Python 3.9 oder höher muss installiert werden.
  • Die AGEFreighter-Bibliothek (AGEFreighter PyPi) muss als Abhängigkeit installiert werden:
poetry add agefreighter

Verwenden des CSV-Datenformats für Benchmarks

Für die Benchmarks wird eine CSV-Datei verwendet, um Daten in AGE zu laden. Das CSV-Format wird häufig unterstützt und lässt sich leicht damit arbeiten, wodurch es eine gute Wahl für das Laden von Daten ist.

Da das Dataset aus Rechtsfällen und Beziehungen zwischen ihnen besteht, ist die CSV-Eingabedatei wie folgt strukturiert:

id,CaseID,start_vertex_type,end_CaseID,end_vertex_type
1,1005631,Case,5030916,Case
2,1005631,Case,5028652,Case
3,1005631,Case,996512,Case
4,1005631,Case,3413065,Case
5,1005631,Case,4912975,Case

Jede Zeile stellt eine Beziehung zwischen zwei Fällen dar. CaseID bezieht sich auf den Start-Case-Knoten, während end_CaseID auf den verbundenen Fall verweist.

Verwenden des Datenladeskripts für Benchmarks

Das folgende Python Skript wurde verwendet, um das Dataset in AGE zu laden. Sie können auch auf den Abschnitt "Verwendung von CSVFreighter" in AGEFreighter PyPi für ein anderes Beispiel verweisen.

await instance.load(
 graph_name="CaseGraphFull",
 start_v_label="Case",
 start_id="CaseID",
 start_props=[],
 edge_type="REF",
 edge_props=[],
 end_v_label="Case",
 end_id="end_CaseID",
 end_props=[],
 csv_path="./cases.csv",
 use_copy=True,
 drop_graph=True,
 create_graph=True,
 progress=True,
)

Wie Sie sehen können, werden hier die graph_name und Felder in der bereitgestellten CSV-Datei definiert. Der parameter use_copy=True stellt ein effizientes Laden von Daten sicher. Die Parameter drop_graph=True und create_graph=True stellen sicher, dass ein neuer Start gestartet wird, bevor neue Daten geladen werden.

Andere Datenquellen

AGEFreighter unterstützt andere Formate wie MultiCSV, Avro, Parkett und Azure Storage, die basierend auf den Datenformatanforderungen angepasst werden können. Weitere Informationen finden Sie unter AGEFreighter auf PyPI.

Benchmarks für die Datenladeleistung

  • Datasetgröße: 725K-Fälle, 2,8M-Beziehungen.
  • Ladezeit: 83 Sekunden.

Effizientes Laden von Daten ist für die effektive Handhabung großer Datasets unerlässlich.

Note

Obwohl sie für große Dateien geeignet sind, kann dieser Prozess aufgrund der Vorbereitungszeit für kleinere Datasets weniger effektiv sein.