Bonnes pratiques pour exécuter des algorithmes sur Spanner Graph

Ce document décrit les bonnes pratiques à suivre pour exécuter des algorithmes sur Spanner Graph. Il aborde les sujets suivants :

Bonnes pratiques concernant le schéma de graphique pour les algorithmes

Si vous utilisez des libellés et des propriétés personnalisés dans Spanner Graph, nous vous recommandons de toujours exposer les clés d' élément en tant que propriétés. Vous pouvez ainsi accéder à ces propriétés clés dans la clause RETURN de la requête d'algorithme et les utiliser pour identifier l'élément de graphe pour lequel l'algorithme génère une sortie.

Gérer la sortie de l'algorithme

Cette section fournit des recommandations sur les éléments à renvoyer à partir de la sortie de l'algorithme et sur l'emplacement où conserver les résultats renvoyés.

Éléments à renvoyer

Lorsque la signature de sortie de l'algorithme contient des éléments de graphique, Spanner Graph vous permet de renvoyer n'importe quelle propriété de ces éléments. Pour réduire les coûts de traitement, nous vous recommandons de limiter la liste des propriétés à renvoyer. Par exemple, ne renvoyez que les propriétés qui sont des clés d'un élément, car les clés sont nécessaires pour identifier l'élément.

Emplacement de conservation

Spanner Graph permet de conserver le résultat de la requête d'algorithme dans Cloud Storage ou dans la même instance Spanner Graph à partir de laquelle vous lancez la requête.

La persistance dans Spanner rend le résultat de l'algorithme accessible à toutes les opérations Spanner de manière native. Par exemple, vous pouvez exécuter WeaklyConnectedComponent et conserver cluster_id dans le graphique. Ensuite, exécutez PageRank pour un graphique d'entrée avec un cluster_id spécifique. Les fonctionnalités Spanner telles que Change Stream propagent les nouvelles sorties d'algorithme vers les systèmes en aval. Si vous souhaitez utiliser le résultat de l'algorithme dans Spanner, nous vous recommandons de le conserver dans Spanner. Bien que Spanner Graph utilise des méthodes efficaces pour regrouper et conserver la sortie de l'algorithme dans Spanner, toutes les écritures doivent passer par le même réplica principal. Si des charges de travail critiques occupent déjà la capacité du réplica principal, vous pouvez échelonner les exécutions d'algorithme pour éviter de concurrencer les charges de travail critiques.

Envisagez de conserver les données dans Cloud Storage si vous ne prévoyez pas d'utiliser le résultat de l'algorithme dans Spanner ou si vous souhaitez évaluer le résultat de l'algorithme avant de l'ingérer dans votre source de données principale. Consultez les formats de fichiers compatibles .

Points à prendre en compte concernant la modélisation des données pour augmenter le graphique

Cette section aborde certains points à prendre en compte concernant la modélisation des données lors de la conservation du résultat de l'algorithme dans Spanner.

Propriétés ou arêtes

Les algorithmes peuvent générer diverses informations, y compris les suivantes :

  • Métriques au niveau des nœuds (par exemple, score de centralité). Elles peuvent être conservées en tant que nouvelles propriétés sur le nœud.
  • Informations par paires (par exemple, similitude entre deux nœuds). Elles peuvent être conservées en tant que nouvelles arêtes entre les deux nœuds, avec la valeur de sortie comme propriété d'arête.
  • Les algorithmes de détection de communauté identifient les communautés logiques dans le graphique et peuvent attribuer une ou plusieurs communautés à un nœud donné. Vous pouvez modéliser l'appartenance à une communauté en tant que nouvelle propriété sur le nœud en balisant chaque nœud membre avec l'ID de sa communauté attribuée. Vous pouvez également modéliser l'appartenance à une communauté en tant que nouveaux sous-graphiques et stocker les communautés logiques en tant que nouveau type de nœuds dans le graphique avec des arêtes les connectant aux nœuds membres. La propriété de communauté peut être suffisante si vous souhaitez connaître la communauté à laquelle appartient un nœud lorsque vous y accédez. Le sous-graphique de communauté peut être plus approprié lorsque vous souhaitez naviguer par communauté (par exemple, trouver des nœuds dans la même communauté qu'un nœud de départ). Selon la façon dont vous prévoyez d'utiliser les informations sur la communauté, vous pouvez choisir l'une ou l'autre, ou les deux.

Schéma prédéfini ou schéma flexible

Avant de conserver la sortie de l'algorithme dans Spanner, définissez la colonne ou la table de destination dans le schéma de l'une des manières suivantes :

  • Si vos cas d'utilisation d'algorithme sont stables et connus, vous pouvez ajouter des colonnes ou des tables supplémentaires à l'avance.
  • Si vous itérez et expérimentez différentes façons d'extraire des informations (par exemple, en essayant différents algorithmes, paramètres, sous-graphiques d'entrée), vous pouvez avoir besoin d'un moyen flexible de conserver et de différencier la sortie de plusieurs expérimentations sans mettre à jour le schéma Spanner pour chaque exécution. Dans ce cas, vous pouvez envisager de stocker les nouvelles propriétés et arêtes produites par les algorithmes dans des tables enfants génériques.

Pour stocker les nouvelles propriétés et arêtes produites par les algorithmes dans des tables enfants génériques, procédez comme suit :

Étape 1 : Créer des tables enfants génériques

-- Create `AccountAlgoProperty` as a child table of `Account`, to store all
-- properties produced by algorithms for `Account`.
-- `algo_run_id`: a unique ID for a given algorithm run.
-- `int_val`: column to store integer algorithm output.
-- `float_val`: column to store float algorithm output.
CREATE TABLE AccountAlgoProperty (
 id INT64 NOT NULL,
 algo_run_id STRING(200) NOT NULL,
 int_val INT64,
 float_val FLOAT64
) PRIMARY KEY(id, algo_run_id),
 INTERLEAVE IN PARENT Account;

-- Create `AccountAlgoEdge` as a child table of `Account`, to store all
-- outgoing edges produced by algorithms for `Account`.
-- `algo_run_id`: a unique ID for a given algorithm run.
-- `to_id`: destination `Account` id.
-- `int_val`: column to store integer algorithm output.
-- `float_val`: column to store float algorithm output.
CREATE TABLE AccountAlgoEdge (
 id INT64 NOT NULL,
 algo_run_id STRING(200) NOT NULL,
 to_id INT64 NOT NULL,
 int_val INT64,
 float_val FLOAT64,
 CONSTRAINT FK_AccountId FOREIGN KEY (to_id) REFERENCES Account (id) NOT ENFORCED,
) PRIMARY KEY(id, algo_run_id, to_id),
 INTERLEAVE IN PARENT Account;

Étape 2 : Stocker les propriétés et les arêtes produites par les algorithmes en tant que lignes de table enfants, ainsi que l'algo_run_id unique qui les a produites.

-- Store PageRank score as property in child table.
EXPORT DATA
 OPTIONS (format = "CLOUD_SPANNER",
          table = "AccountAlgoProperty",
          write_mode = 'upsert_ignore_all' ) AS
GRAPH FinGraph
CALL PageRank(node_labels => ['Account'], edge_labels => ['Transfers'])
RETURN node.id, "page_rank_123" AS algo_run_id, score As float_val;

-- Store ShortestPath output as edge in child table.
EXPORT DATA
 OPTIONS (format = "CLOUD_SPANNER",
          table = "AccountAlgoEdge",
          write_mode = 'upsert_ignore_all' ) AS
GRAPH FinGraph
CALL ShortestPath(
    source_nodes => ARRAY {
                      MATCH (n:Account {id: 7})
                      RETURN n
                    },
    target_nodes => ARRAY {
                      MATCH (n:Account {id: 16})
                      RETURN n
                    }
  ) YIELD source_node, target_node, path, cost
RETURN source_node.id AS id, "shortest_path_456" AS algo_run_id,
  target_node.id AS to_id, PATH_LENGTH(path) AS int_val, cost AS float_val;

Étape 3 : Accéder à la sortie de l'algorithme à l'aide de GRAPH_TABLE

SELECT acct.id, prop.float_val AS page_rank_score
FROM GRAPH_TABLE(
  FinGraph
  MATCH (n:Account)
  RETURN n.id
) acct JOIN AccountAlgoProperty prop ON acct.id = prop.id
  AND prop.algo_run_id = 'page_rank_123';

SELECT acct.id, edge.to_id, edge.int_val AS path_len, edge.float_val AS cost
FROM GRAPH_TABLE(
  FinGraph
  MATCH (n:Account)
  RETURN n.id
) acct JOIN AccountAlgoEdge edge ON acct.id = edge.id
  AND edge.algo_run_id = 'shortest_path_456';

Étape 4 : Vous pouvez également créer un graphe logique augmenté avec des propriétés et des arêtes générées par l'algorithme pour faciliter l'accès au résultat de l'algorithme.

-- Create a view that aggregates non-null algorithm properties per node into
-- name-value pairs in JSON.
CREATE OR REPLACE VIEW AccountWithAlgoProperties SQL SECURITY INVOKER AS
SELECT
  n.id, ANY_VALUE(n.create_time) AS create_time,
  ANY_VALUE(n.is_blocked) AS is_blocked, ANY_VALUE(n.nick_name) AS nick_name,
  JSON_OBJECT(
    IF(COUNT(c.algo_run_id) = 0, [], ARRAY_AGG(c.algo_run_id)),
    IF(COUNT(c.algo_run_id) = 0, [], ARRAY_AGG(
      COALESCE(
        IF (c.int_val IS NULL, NULL, TO_JSON(c.int_val)),
        IF (c.float_val IS NULL, NULL, TO_JSON(c.float_val))
      )))) AS algo_props
FROM Account AS n LEFT JOIN AccountAlgoProperty AS c ON n.id = c.id
GROUP BY n.id;

-- Create FinGraphAugmented with algorithm generated properties and edges.
CREATE OR REPLACE PROPERTY GRAPH FinGraphAugmented
  NODE TABLES (
    AccountWithAlgoProperties AS Account
      KEY(id)
      LABEL Account PROPERTIES(
        create_time,
        id,
        is_blocked,
        nick_name,
        algo_props),
    Person
  )
  EDGE TABLES (
    PersonOwnAccount
      SOURCE KEY (id) REFERENCES Person (id)
      DESTINATION KEY (account_id) REFERENCES Account (id)
      LABEL Owns,
    AccountTransferAccount
      SOURCE KEY (id) REFERENCES Account (id)
      DESTINATION KEY (to_id) REFERENCES Account (id)
      LABEL Transfers,
    AccountAlgoEdge
      SOURCE KEY (id) REFERENCES Account (id)
      DESTINATION KEY (to_id) REFERENCES Account (id)
  );

Vous pouvez ensuite accéder directement aux propriétés de l'algorithme et parcourir les arêtes générées par l'algorithme dans la requête de graphique :

-- Retrieve PageRank score property in graph query.
GRAPH FinGraphAugmented
MATCH (a:Account)
RETURN a.id, a.algo_props.page_rank_123 AS page_rank
ORDER BY page_rank DESC
LIMIT 5;

-- Navigate through ShortestPath edge in graph query.
GRAPH FinGraphAugmented
MATCH (s:Account {id: 7})-[e:AccountAlgoEdge {algo_run_id : 'shortest_path_456'}]->(d:Account)
RETURN s.id AS src, d.id AS dst, e.int_val AS path_len, e.float_val AS cost

Spécifier machine_category pour les charges de travail volumineuses

Pour la plupart des charges de travail, la `machine_category` default est appropriée. Si votre graphique d'entrée comporte plus d'un milliard de nœuds et plus de 10 milliards d'arêtes, nous vous recommandons de choisir explicitement large pour machine_category.

Réutiliser le calcul pour une itération rapide

Si vous expérimentez différents algorithmes ou différents paramètres d'entrée sur de petits ensembles de données pour une itération rapide, nous vous recommandons d'utiliser max_idle_time. Un max_idle_time Spanner Graph plus important vous permet de réutiliser les ressources de calcul qu'il a déjà provisionnées pour davantage de charges de travail d'algorithme. Cela réduit la surcharge du démarrage à froid du calcul à la demande et atténue le risque de ne pas pouvoir provisionner le calcul en raison d'un manque temporaire de capacité. Notez que le calcul de l'algorithme est facturable lorsqu'il est inactif.

Différencier les types d'éléments dans la sortie

Si la sortie de l'algorithme contient plusieurs types d'éléments, vous pouvez inclure ELEMENT_DEFINITION_NAME dans votre sortie pour les différencier. Exemple :

EXPORT DATA OPTIONS (
  uri = "gs://bucket-name/page_rank.csv",
  format = "csv",
  overwrite = TRUE) AS
GRAPH FinGraph
CALL PageRank()
YIELD node, score
RETURN ELEMENT_DEFINITION_NAME(node) AS node_type, node.id, score;

Étape suivante