Partager via


Meilleures pratiques : indexation, AGE EXPLAIN et benchmarks de charge de données

Apache AGE pris en charge par Azure Database pour PostgreSQL fournit la prise en charge du traitement et de l’interrogation avancés des graphiques. Toutefois, l’obtention de performances optimales des requêtes nécessite une stratégie réfléchie pour l’indexation et le chargement des données. Ce guide décrit certaines meilleures pratiques basées sur les résultats de référence récents et les insights techniques.

Indexation dans Apache AGE

L’indexation est essentielle pour améliorer les performances des requêtes, en particulier dans les bases de données de graphe.

Comportement par défaut

Par défaut, Apache AGE ne crée pas d’index pour les graphiques nouvellement créés. Cela nécessite la création explicite d’index en fonction de la nature de vos requêtes et de votre jeu de données.

WHERE (clause)

Dans Apache AGE, les requêtes suivantes sont évaluées différemment :

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);

Pour tirer pleinement parti de l’indexation, vous devez comprendre quels types d’index sont utilisés par des requêtes avec et sans clause WHERE.

EXPLAIN dans Apache AGE

Contrairement à SQL standard, le mot clé EXPLAIN dans les requêtes de chiffrement nécessite un format de requête différent.

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)

Pour voir les différences entre les plans de requête sans clause WHERE :

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)

Types d’index courants

  • Index BTREE : effectif pour les correspondances exactes et les requêtes de plage. Recommandé pour une utilisation avec des colonnes telles qu’ID, start_id et end_id dans les tables de bord et de vertex.
  • Index GIN : utile pour les champs JSON, ce qui permet de rechercher efficacement des paires clé-valeur dans la colonne de propriétés.

Utilisez les commandes suivantes pour créer des index pour les tables de vertex et de bord :

  • Tableau de sommets :

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

    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);
    

Indexation d’une clé-valeur spécifique dans les propriétés

Pour les requêtes ciblées, un index BTREE plus petit et plus efficace peut être créé pour des clés spécifiques dans la colonne de propriétés :

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

Cette approche évite d’indexer des données inutiles, ce qui améliore l’efficacité.

Insights de plan de requête avec EXPLAIN

Le mot clé EXPLAIN révèle comment les requêtes utilisent des index. Toutes les requêtes n’utilisent pas automatiquement des index, en particulier ceux émis sans clause WHERE. Utilisez EXPLAIN pour vérifier l’utilisation de l’index et optimiser les requêtes en conséquence.

Observations de référence

Les tests récents mettent en évidence l’impact de l’indexation sur les performances des requêtes.

Requêtes indexées et non indexées

Cette section décrit les différences de performances entre les requêtes indexées et non indexées.

  • Les analyses séquentielles surperforment les analyses d’index pour les requêtes récupérant des tables entières.
  • L’indexation améliore considérablement les performances des requêtes de jointure (par exemple, le nombre de relations).

Meilleures pratiques de chargement des données

Le chargement efficace des données est essentiel pour les jeux de données volumineux.

La bibliothèque AGEFreighter offre un processus simplifié pour l’ingestion des données.

Chargement des données avec AGEFreighter

AGEFreighter est une bibliothèque Python conçue pour faciliter le chargement des données dans Apache AGE. Il prend en charge différents formats de données, notamment CSV, Avro et Parquet, et fournit une interface simple pour le chargement de données dans des graphiques AGE.

Configuration de l’environnement

  • Création d’un serveur flexible Azure Database pour PostgreSQL avec AGE activé.
  • L’outil de gestion des dépendances Python tel que La poésie est recommandé. Python 3.9 ou version ultérieure doit être installé.
  • La bibliothèque AGEFreighter (AGEFreighter PyPi) doit être installée en tant que dépendance :
poetry add agefreighter

Utiliser le format de données CSV pour les benchmarks

Pour les benchmarks, j’ai utilisé un fichier CSV pour charger des données dans AGE. Le format CSV est largement pris en charge et facile à utiliser, ce qui en fait un bon choix pour les tâches de chargement de données.

Étant donné que le jeu de données utilisé se compose de cas juridiques et de relations entre eux, j’ai structuré mon fichier CSV d’entrée comme suit :

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

Chaque ligne représente une relation entre deux cas. CaseID fait référence au nœud de cas de départ, tandis que end_CaseID fait référence au cas connecté.

Utiliser le script de chargement des données pour les benchmarks

Le script Python suivant a été utilisé pour charger mon jeu de données dans AGE. Vous pouvez également faire référence à la section « Utilisation de CSVFreighter » dans AGEFreighter PyPi pour obtenir un autre exemple.

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,
)

Comme vous pouvez le voir, le graph_name et les champs du fichier csv fourni sont définis ici. Le paramètre use_copy=True garantit un chargement efficace des données. Les paramètres drop_graph=True et create_graph=True garantissent un nouveau démarrage avant de charger de nouvelles données.

Autres sources de données

AGEFreighter prend en charge d’autres formats tels que MultiCSV, Avro, Parquet, Stockage Azure, etc. qui peuvent être adaptés en fonction des exigences de format de données. Vous pouvez obtenir plus d’informations ici : « AGEFreighter PyPi »

Benchmarks de performances de chargement des données

  • Taille du jeu de données : 725 000 cas, 2,8M relations.
  • Temps de chargement : 83 secondes.

Le chargement efficace des données est essentiel pour la gestion efficace des jeux de données volumineux.

Remarque

Bien qu’il soit adapté aux fichiers volumineux, ce processus peut être moins efficace pour les jeux de données plus petits en raison du temps de préparation.