Best Practices für die Ausführung von Algorithmen in Spanner Graph

In diesem Dokument werden Best Practices für das Ausführen von Algorithmen in Spanner Graph beschrieben. Es deckt folgende Themenbereiche ab:

Best Practices für das Diagrammschema für Algorithmen

Wenn Sie benutzerdefinierte Labels und Properties in Spanner Graph verwenden, empfehlen wir, immer Elementschlüssel als Properties verfügbar zu machen. So können Sie in der RETURN-Klausel der Algorithmusabfrage auf diese wichtigen Eigenschaften zugreifen und damit das Grafikelement identifizieren, für das der Algorithmus eine Ausgabe generiert.

Algorithmusausgabe verarbeiten

In diesem Abschnitt finden Sie Empfehlungen dazu, was aus der Algorithmusausgabe zurückgegeben werden sollte und wo die zurückgegebenen Ergebnisse gespeichert werden sollten.

Was zurückgegeben werden muss

Wenn die Ausgabesignatur des Algorithmus Grafikelemente enthält, können Sie mit Spanner Graph eine beliebige Eigenschaft dieser Elemente zurückgeben. Um die Verarbeitungskosten zu senken, empfehlen wir, die Liste der zurückzugebenden Properties zu minimieren. Geben Sie beispielsweise nur Attribute zurück, die Schlüssel eines Elements sind, da Schlüssel zum Identifizieren des Elements erforderlich sind.

Speicherort

Spanner Graph unterstützt das Speichern von Algorithmusabfrageergebnissen in Cloud Storage oder in derselben Spanner Graph-Instanz, in der Sie die Abfrage starten.

Durch das Zurückschreiben in Spanner ist die Ausgabe des Algorithmus nativ für alle Spanner-Vorgänge verfügbar. Sie können beispielsweise WeaklyConnectedComponent ausführen und cluster_id im Diagramm beibehalten. Führen Sie anschließend PageRank für einen Eingabegraphen mit bestimmten cluster_id aus. Spanner-Funktionen wie Change Stream übertragen neue Algorithmusausgaben an nachgelagerte Systeme. Wenn Sie die Algorithmusausgabe in Spanner verwenden möchten, empfehlen wir, sie in Spanner zu speichern. Spanner Graph verwendet zwar effiziente Methoden, um Algorithmusausgaben in Batches zu verarbeiten und in Spanner zu speichern, aber alle Schreibvorgänge müssen über das gleiche Leader-Replikat erfolgen. Wenn Sie bereits kritische Arbeitslasten haben, die Leader-Kapazität in Anspruch nehmen, sollten Sie die Algorithmusausführungen staffeln, um Konflikte mit kritischen Arbeitslasten zu vermeiden.

Daten in Cloud Storage speichern ist eine gute Option, wenn Sie die Algorithmusausgabe nicht in Spanner verwenden oder sie vor dem Importieren in Ihre primäre Datenquelle auswerten möchten. Unterstützte Dateiformate

Überlegungen zur Datenmodellierung für die Erweiterung des Diagramms

In diesem Abschnitt werden einige Überlegungen zur Datenmodellierung beim Speichern von Algorithmusausgaben in Spanner behandelt.

Attribute im Vergleich zu Kanten

Algorithmen können eine Vielzahl von Statistiken liefern, darunter:

  • Messwerte auf Knotenebene (z. B. Zentralitätswert) Diese können als neue Attribute für den Knoten gespeichert werden.
  • Paarweise Statistiken (z. B. Ähnlichkeit zwischen zwei Knoten) Diese können als neue Kanten zwischen den beiden Knoten mit dem Ausgabewert als Kanteneigenschaft gespeichert werden.
  • Algorithmen zur Community-Erkennung identifizieren logische Communities im Diagramm und können einem bestimmten Knoten eine oder mehrere Communities zuweisen. Sie können die Community-Mitgliedschaft als neue Eigenschaft für den Knoten modellieren, indem Sie jeden Mitgliedsknoten mit der ID der zugewiesenen Community taggen. Sie können die Community-Mitgliedschaft auch als neue Untergraphen modellieren und die logischen Communities als neuen Knotentyp im Graphen speichern. Die Knoten werden dann über Kanten mit den Mitgliedsknoten verbunden. Community-Eigenschaften können ausreichen, wenn Sie wissen möchten, zu welcher Community ein Knoten gehört, wenn Sie auf einen Knoten zugreifen. Der Community-Teilgraph ist möglicherweise besser geeignet, wenn Sie nach Community navigieren möchten, z. B. um Knoten in derselben Community wie ein Startknoten zu finden. Je nachdem, wie Sie Community-Informationen verwenden möchten, können Sie eine oder beide Optionen auswählen.

Vordefiniertes Schema im Vergleich zu flexiblem Schema

Bevor Sie die Algorithmusausgabe in Spanner speichern, müssen Sie die Zielspalte oder -tabelle im Schema auf eine der folgenden Arten definieren:

  • Wenn Ihre Anwendungsfälle für Algorithmen stabil und bekannt sind, können Sie im Voraus zusätzliche Spalten oder Tabellen hinzufügen.
  • Wenn Sie verschiedene Methoden zum Extrahieren von Statistiken durchlaufen und testen (z. B. verschiedene Algorithmen, Parameter, Eingabe-Untergraphen ausprobieren), benötigen Sie möglicherweise eine flexible Möglichkeit, die Ausgabe aus mehreren Tests beizubehalten und zu unterscheiden, ohne das Spanner-Schema für jeden Lauf zu aktualisieren. In diesem Fall können Sie in Erwägung ziehen, neue Eigenschaften und Kanten, die von Algorithmen generiert werden, in generischen untergeordneten Tabellen zu speichern.

So speichern Sie neue Eigenschaften und Kanten, die von Algorithmen generiert werden, in generischen untergeordneten Tabellen:

Schritt 1: Allgemeine untergeordnete Tabellen erstellen

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

Schritt 2: Speichern Sie die von Algorithmen erstellten Attribute und Kanten als untergeordnete Tabellenzeilen zusammen mit der eindeutigen algo_run_id, die sie erzeugt hat.

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

Schritt 3: Auf die Algorithmusausgabe zugreifen mit 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';

Schritt 4: Optional einen logischen Graphen erstellen, der mit algorithmisch generierten Attributen und Kanten erweitert wird, um den Zugriff auf die Algorithmusausgabe zu erleichtern.

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

Anschließend können Sie direkt auf Algorithmusattribute zugreifen und in der Diagrammabfrage durch die vom Algorithmus generierten Kanten navigieren:

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

machine_category für große Arbeitslasten angeben

Für die meisten Arbeitslasten ist die default-Kategorie „machine_category“ geeignet. Wenn Ihr Eingabediagramm mehr als 1 Milliarde Knoten und mehr als 10 Milliarden Kanten hat, empfehlen wir, large für machine_category explizit auszuwählen.

Rechenleistung für schnelle Iterationen wiederverwenden

Wenn Sie mit verschiedenen Algorithmen oder verschiedenen Eingabeparametern für kleine Datasets experimentieren, um schnell Iterationen durchzuführen, empfehlen wir Ihnen, max_idle_time zu verwenden. Mit einem größeren max_idle_time-Spanner-Diagramm können Sie bereits bereitgestellte Rechenressourcen für weitere Algorithmusarbeitslasten wiederverwenden. Dadurch wird der Aufwand für das On-Demand-Kaltstarten von Compute-Ressourcen reduziert und das Risiko gemindert, dass Compute-Ressourcen aufgrund eines vorübergehenden Kapazitätsmangels nicht bereitgestellt werden können. Beachten Sie, dass die Berechnung von Algorithmen auch im Leerlauf abrechenbar ist.

Elementtypen in der Ausgabe unterscheiden

Wenn die Algorithmusausgabe mehrere Elementtypen enthält, sollten Sie ELEMENT_DEFINITION_NAME in die Ausgabe einfügen, um sie zu unterscheiden. Beispiel:

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;

Nächste Schritte