Best Practices für das Entwerfen eines Spanner-Graphschemas

In diesem Dokument wird beschrieben, wie Sie mithilfe von Best Practices für das Entwerfen von Spanner-Graphschemas effiziente Abfragen erstellen. Sie können Ihr Schemadesign iterieren. Wir empfehlen daher, zuerst kritische Abfragemuster zu identifizieren, die als Grundlage für Ihr Schemadesign dienen.

Allgemeine Informationen zu Best Practices für das Spanner-Schemadesign finden Sie unter Best Practices für Schemadesign.

Kantendurchlauf optimieren

Bei der Kantenüberquerung wird ein Graph durchlaufen, indem die Kanten ab einem bestimmten Knoten entlang verbundener Kanten zu anderen Knoten verfolgt werden. Die Richtung der Kante wird durch das Schema definiert. Das Durchlaufen von Kanten ist eine grundlegende Operation in Spanner-Graphen. Daher ist die Verbesserung der Effizienz des Kantendurchlaufs entscheidend für die Leistung Ihrer Anwendung.

Sie können eine Kante in zwei Richtungen durchlaufen:

  • Vorwärtskantendurchlauf: Es werden ausgehende Kanten des Quellknotens verfolgt.

  • Reverse Edge Traversal: Es werden die eingehenden Kanten des Zielknotens abgearbeitet.

Bei einer Person führt die folgende Beispielabfrage eine vorwärtsgerichtete Kantendurchquerung der Owns-Kanten aus:

GRAPH FinGraph
MATCH (person:Person {id: 1})-[owns:Owns]->(accnt:Account)
RETURN accnt.id;

In der folgenden Beispielabfrage wird für ein Konto eine umgekehrte Kantendurchquerung von Owns Kanten ausgeführt:

GRAPH FinGraph
MATCH (accnt:Account {id: 1})<-[owns:Owns]-(person:Person)
RETURN person.name;

Vorwärtskantendurchlauf mithilfe von Interleaving optimieren

Um die Leistung der Vorwärtskantenüberprüfung zu verbessern, verschränken Sie die Eingabetabelle für Kanten mit der Eingabetabelle für Quellknoten, um Kanten mit Quellknoten zu platzieren. Die Verschränkung ist eine Speicheroptimierungstechnik in Spanner, bei der Zeilen der untergeordneten Tabelle zusammen mit den entsprechenden übergeordneten Zeilen im Speicher physisch zusammen gespeichert werden. Weitere Informationen zum Interleaving finden Sie unter Schemas – Übersicht.

Das folgende Beispiel veranschaulicht diese Best Practices:

CREATE TABLE Person (
  id               INT64 NOT NULL,
  name             STRING(MAX),
) PRIMARY KEY (id);

CREATE TABLE PersonOwnAccount (
  id               INT64 NOT NULL,
  account_id       INT64 NOT NULL,
  create_time      TIMESTAMP,
) PRIMARY KEY (id, account_id),
  INTERLEAVE IN PARENT Person ON DELETE CASCADE;

Rückwärtsgerichtete Kantenüberprüfung mithilfe von Fremdschlüsseln optimieren

Wenn Sie Rückstiche effizient durchlaufen möchten, erstellen Sie eine erzwungene Fremdschlüsseleinschränkung zwischen dem Pfad und dem Zielknoten. Dieser erzwungene Fremdschlüssel erstellt einen Sekundärindex für die Kante, der anhand der Zielknotenschlüssel geordnet wird. Der sekundäre Index wird bei der Abfrageausführung automatisch verwendet.

Das folgende Beispiel veranschaulicht diese Best Practices:

CREATE TABLE Person (
  id               INT64 NOT NULL,
  name             STRING(MAX),
) PRIMARY KEY (id);

CREATE TABLE Account (
  id               INT64 NOT NULL,
  create_time      TIMESTAMP,
) PRIMARY KEY (id);

CREATE TABLE PersonOwnAccount (
  id               INT64 NOT NULL,
  account_id       INT64 NOT NULL,
  create_time      TIMESTAMP,
  CONSTRAINT FK_Account FOREIGN KEY (account_id) REFERENCES Account (id),
) PRIMARY KEY (id, account_id),
  INTERLEAVE IN PARENT Person ON DELETE CASCADE;

Rückwärtsgerichtete Kantenüberprüfung mithilfe eines sekundären Index optimieren

Wenn Sie keinen erzwungenen Fremdschlüssel auf der Kante erstellen möchten, z. B. aufgrund der strengen Datenintegrität, die er erzwingt, können Sie direkt einen sekundären Index in der Edge-Eingabetabelle erstellen, wie im folgenden Beispiel gezeigt:

CREATE TABLE PersonOwnAccount (
  id               INT64 NOT NULL,
  account_id       INT64 NOT NULL,
  create_time      TIMESTAMP,
) PRIMARY KEY (id, account_id),
  INTERLEAVE IN PARENT Person ON DELETE CASCADE;

CREATE INDEX Reverse_PersonOwnAccount
ON PersonOwnAccount (account_id);

Kantendurchlauf mithilfe von informativen Fremdschlüsseln optimieren

Wenn Ihr Szenario Engpässe bei der Schreibleistung aufweist, die durch erzwungene Fremdschlüssel verursacht werden, z. B. bei häufigen Aktualisierungen von Hubknoten mit vielen verbundenen Kanten, sollten Sie erwägen, informative Fremdschlüssel zu verwenden. Wenn Sie informative Fremdschlüssel in den Referenzspalten einer Kantentabelle verwenden, kann der Abfrageoptimierer redundante Knotentabellenscans entfernen. Da für informative Fremdschlüssel jedoch keine sekundären Indizes in der Kantentabelle erforderlich sind, wird die Geschwindigkeit der Suchanfragen nicht verbessert, wenn in einer Abfrage versucht wird, Kanten mit Endknoten zu finden. Weitere Informationen finden Sie unter Vergleich der Fremdschlüsseltypen.

Wenn Ihre Anwendung die referentielle Integrität nicht gewährleisten kann, kann die Verwendung von informativen Fremdschlüsseln für die Abfrageoptimierung zu falschen Abfrageergebnissen führen.

Im folgenden Beispiel wird eine Tabelle mit einem informativen Fremdschlüssel in der Spalte account_id erstellt:

CREATE TABLE PersonOwnAccount (
  id               INT64 NOT NULL,
  account_id       INT64 NOT NULL,
  create_time      TIMESTAMP,
  CONSTRAINT FK_Account FOREIGN KEY (account_id)
    REFERENCES Account (id) NOT ENFORCED
) PRIMARY KEY (id, account_id),
  INTERLEAVE IN PARENT Person ON DELETE CASCADE;

Wenn das Interleaving nicht möglich ist, können Sie beide Kantenreferenzen mit informativen Fremdschlüsseln kennzeichnen, wie im folgenden Beispiel:

CREATE TABLE PersonOwnAccount (
  id               INT64 NOT NULL,
  account_id       INT64 NOT NULL,
  create_time      TIMESTAMP,
  CONSTRAINT FK_Person FOREIGN KEY (id)
    REFERENCES Person (id) NOT ENFORCED,
  CONSTRAINT FK_Account FOREIGN KEY (account_id)
    REFERENCES Account (id) NOT ENFORCED
) PRIMARY KEY (id, account_id);

Lose Kanten nicht zulassen

Eine lose Kante ist eine Kante, die weniger als zwei Knoten verbindet. Ein ungebundener Kanten kann auftreten, wenn ein Knoten gelöscht wird, ohne die zugehörigen Kanten zu entfernen, oder wenn eine Kante erstellt wird, ohne sie richtig mit den Knoten zu verknüpfen.

Das Ausschließen von in der Luft hängenden Kanten bietet folgende Vorteile:

  • Erzwingt die Integrität der Graphstruktur.
  • Verbessert die Abfrageleistung, da nicht benötigte Kanten, an denen keine Endpunkte vorhanden sind, herausgefiltert werden.

Mithilfe von referenziellen Einschränkungen lose Kanten verhindern

Wenn Sie lose Kanten nicht zulassen möchten, geben Sie Einschränkungen für beide Endpunkte an:

  • Intercalieren Sie die Eingabetabelle für Kanten in die Eingabetabelle für Quellknoten. Dadurch wird sichergestellt, dass der Quellknoten einer Kante immer vorhanden ist.
  • Erstellen Sie eine erzwungene Fremdschlüsseleinschränkung für Kanten, damit der Zielknoten einer Kante immer vorhanden ist.

Im folgenden Beispiel werden Interleaving und ein erzwungener Fremdschlüssel verwendet, um die referenzielle Integrität zu erzwingen:

CREATE TABLE PersonOwnAccount (
  id               INT64 NOT NULL,
  account_id       INT64 NOT NULL,
  create_time      TIMESTAMP,
  CONSTRAINT FK_Account FOREIGN KEY (account_id) REFERENCES Account (id) ON DELETE CASCADE,
) PRIMARY KEY (id, account_id),
  INTERLEAVE IN PARENT Person ON DELETE CASCADE;

ON DELETE CASCADE verwenden, um beim Löschen eines Knotens automatisch Kanten zu entfernen

Wenn Sie Interleaving oder einen erzwungenen Fremdschlüssel verwenden, um lose Kanten zu verhindern, können Sie mit der Klausel ON DELETE festlegen, was passieren soll, wenn Sie einen Knoten mit noch verbundenen Kanten löschen möchten. Weitere Informationen finden Sie unter Kettenlöschung für verschränkte Tabellen und Fremdschlüsselaktionen.

Sie können ON DELETE auf folgende Arten verwenden:

  • ON DELETE NO ACTION (oder Auslassen der Klausel ON DELETE): Das Löschen eines Knotens mit Kanten schlägt fehl.
  • ON DELETE CASCADE: Wenn Sie einen Knoten löschen, werden die zugehörigen Kanten in derselben Transaktion automatisch entfernt.

Löschen der Kaskade für Kanten, die verschiedene Knotentypen verbinden

  • Kanten löschen, wenn der Quellknoten gelöscht wird. Mit INTERLEAVE IN PARENT Person ON DELETE CASCADE werden beispielsweise alle ausgehenden PersonOwnAccount-Kanten aus dem zu löschenden Knoten Person gelöscht. Weitere Informationen finden Sie unter Verschachtelte Tabellen erstellen.

  • Kanten löschen, wenn der Zielknoten gelöscht wird Mit CONSTRAINT FK_Account FOREIGN KEY(account_id) REFERENCES Account(id) ON DELETE CASCADE werden beispielsweise alle eingehenden PersonOwnAccount-Kanten zum zu löschenden Knoten Account gelöscht.

Löschen der Kaskade für Kanten, die Knoten desselben Typs verbinden

Wenn Quell- und Zielknoten einer Kante denselben Typ haben und die Kante in den Quellknoten verschachtelt ist, können Sie ON DELETE CASCADE nur für den Quell- oder Zielknoten definieren, aber nicht für beide Knoten.

Um in beiden Fällen lose Kanten zu entfernen, erstellen Sie einen erzwungenen Fremdschlüssel für die Referenz des Quellknotens der Kante, anstatt die Eingabetabelle der Kante in die Eingabetabelle des Quellknotens einzufügen.

Wir empfehlen das Interleaving, um die Vorwärtskantensuche zu optimieren. Prüfen Sie vor dem Fortfahren, welche Auswirkungen die Änderung auf Ihre Arbeitslasten hat. Im folgenden Beispiel wird AccountTransferAccount als Edge-Eingabetabelle verwendet:

--Define two Foreign Keys, each on one end Node of Transfer Edge, both with ON DELETE CASCADE action:
CREATE TABLE AccountTransferAccount (
  id               INT64 NOT NULL,
  to_id            INT64 NOT NULL,
  amount           FLOAT64,
  create_time      TIMESTAMP NOT NULL,
  order_number     STRING(MAX),
  CONSTRAINT FK_FromAccount FOREIGN KEY (id) REFERENCES Account (id) ON DELETE CASCADE,
  CONSTRAINT FK_ToAccount FOREIGN KEY (to_id) REFERENCES Account (id) ON DELETE CASCADE,
) PRIMARY KEY (id, to_id);

Mithilfe von Sekundärindexen nach Knoten- oder Kanteneigenschaften filtern

Sekundäre Indexe sind für die effiziente Abfrageverarbeitung unerlässlich. Sie unterstützen schnelle Suchanfragen nach Knoten und Kanten anhand bestimmter Attributwerte, ohne die gesamte Graphstruktur durchsuchen zu müssen. Das ist wichtig, wenn Sie mit großen Graphen arbeiten, da das Durchlaufen aller Knoten und Kanten sehr ineffizient sein kann.

Filtern von Knoten nach Property beschleunigen

Wenn Sie das Filtern nach Knoteneigenschaften beschleunigen möchten, erstellen Sie sekundäre Indexe für Properties. Mit der folgenden Abfrage werden beispielsweise Konten für einen bestimmten Alias gefunden. Ohne sekundären Index werden alle Account-Knoten auf Übereinstimmung mit den Filterkriterien geprüft.

GRAPH FinGraph
MATCH (acct:Account)
WHERE acct.nick_name = "abcd"
RETURN acct.id;

Um die Abfrage zu beschleunigen, erstellen Sie einen sekundären Index für die gefilterte Property, wie im folgenden Beispiel gezeigt:

CREATE TABLE Account (
  id               INT64 NOT NULL,
  create_time      TIMESTAMP,
  is_blocked       BOOL,
  nick_name        STRING(MAX),
) PRIMARY KEY (id);

CREATE INDEX AccountByNickName
ON Account (nick_name);

Tipp:Verwenden Sie NULL-gefilterte Indexe für spärliche Properties. Weitere Informationen finden Sie unter Indexierung von NULL-Werten deaktivieren.

Vorwärts-Kantendurchlauf mit Filterung nach Kanteneigenschaften beschleunigen

Wenn Sie einen Kantenknoten durchlaufen und dabei nach seinen Eigenschaften filtern, können Sie die Abfrage beschleunigen, indem Sie einen sekundären Index für die Kanteneigenschaften erstellen und den Index in den Quellknoten einfügen.

Mit der folgenden Abfrage werden beispielsweise Konten gefunden, die nach einem bestimmten Zeitraum zu einer bestimmten Person gehören:

GRAPH FinGraph
MATCH (person:Person)-[owns:Owns]->(acct:Account)
WHERE person.id = 1
  AND owns.create_time >= PARSE_TIMESTAMP("%c", "Thu Dec 25 07:30:00 2008")
RETURN acct.id;

Standardmäßig werden mit dieser Abfrage alle Kanten der angegebenen Person gelesen und dann die Kanten herausgefiltert, die die Bedingung für create_time erfüllen.

Im folgenden Beispiel wird gezeigt, wie Sie die Abfrageleistung verbessern, indem Sie einen sekundären Index für die Referenz des Knotens mit dem Quellknoten (id) und die Kanteneigenschaft (create_time) erstellen. Intercalieren Sie den Index unter der Eingabetabelle des Quellknotens, um ihn mit dem Quellknoten zu verknüpfen.

CREATE TABLE PersonOwnAccount (
  id               INT64 NOT NULL,
  account_id       INT64 NOT NULL,
  create_time      TIMESTAMP,
) PRIMARY KEY (id, account_id),
  INTERLEAVE IN PARENT Person ON DELETE CASCADE;

CREATE INDEX PersonOwnAccountByCreateTime
ON PersonOwnAccount (id, create_time)
INTERLEAVE IN Person;

Mit diesem Ansatz können mit der Abfrage alle Kanten effizient gefunden werden, die die Bedingung für create_time erfüllen.

Durch Filterung nach Kanteneigenschaften die umgekehrte Kantendurchquerung beschleunigen

Wenn Sie einen umgekehrten Kanten durchlaufen und dabei nach den zugehörigen Eigenschaften filtern, können Sie die Abfrage beschleunigen, indem Sie einen sekundären Index mit dem Zielknoten und den Kanteneigenschaften zum Filtern erstellen.

In der folgenden Beispielabfrage wird eine umgekehrte Kantendurchquerung mit Filterung nach Kanteneigenschaften durchgeführt:

GRAPH FinGraph
MATCH (acct:Account)<-[owns:Owns]-(person:Person)
WHERE acct.id = 1
  AND owns.create_time >= PARSE_TIMESTAMP("%c", "Thu Dec 25 07:30:00 2008")
RETURN person.id;

Sie können diese Abfrage mit einem sekundären Index beschleunigen. Verwenden Sie dazu eine der folgenden Optionen:

  • Erstellen Sie einen sekundären Index für die Edge-Zielknotenreferenz (account_id) und die Edge-Eigenschaft (create_time), wie im folgenden Beispiel gezeigt:

    CREATE TABLE PersonOwnAccount (
      id               INT64 NOT NULL,
      account_id       INT64 NOT NULL,
      create_time      TIMESTAMP,
    ) PRIMARY KEY (id, account_id),
      INTERLEAVE IN PARENT Person ON DELETE CASCADE;
    
    CREATE INDEX PersonOwnAccountByCreateTime
    ON PersonOwnAccount (account_id, create_time);
    

    Dieser Ansatz bietet eine bessere Leistung, da die umgekehrten Kanten nach account_id und create_time sortiert werden. So kann die Abfragemaschine effizienter Kanten für account_id finden, die die Bedingung für create_time erfüllen. Wenn jedoch verschiedene Abfragemuster nach verschiedenen Properties filtern, kann für jede Property ein separater Index erforderlich sein, was zu einem zusätzlichen Overhead führen kann.

  • Erstellen Sie einen sekundären Index für die Edge-Zielknotenreferenz (account_id) und speichern Sie die Edge-Eigenschaft (create_time) in einer Speicherspalte, wie im folgenden Beispiel gezeigt:

    CREATE TABLE PersonOwnAccount (
      id               INT64 NOT NULL,
      account_id       INT64 NOT NULL,
      create_time      TIMESTAMP,
    ) PRIMARY KEY (id, account_id),
      INTERLEAVE IN PARENT Person ON DELETE CASCADE;
    
    CREATE INDEX PersonOwnAccountByCreateTime
    ON PersonOwnAccount (account_id) STORING (create_time);
    

    Mit diesem Ansatz können mehrere Eigenschaften gespeichert werden. Die Abfrage muss jedoch alle Kanten des Zielknotens lesen und dann nach Kanteneigenschaften filtern.

Sie können diese Ansätze kombinieren. Beachten Sie dabei Folgendes:

  • Verwenden Sie Kanteneigenschaften in Indexspalten, wenn sie in leistungskritischen Abfragen verwendet werden.
  • Fügen Sie Attribute, die in weniger leistungssensiblen Abfragen verwendet werden, den Speicherspalten hinzu.

Knoten- und Kantentypen mit Labels und Eigenschaften modellieren

Knoten- und Kantentypen werden häufig mit Labels modelliert. Sie können Typen aber auch mithilfe von Properties modellieren. Angenommen, es gibt viele verschiedene Kontotypen, z. B. BankAccount, InvestmentAccount und RetirementAccount. Sie können die Konten in separaten Eingabetabellen speichern und als separate Labels modellieren oder sie in einer einzigen Eingabetabelle speichern und mithilfe einer Property zwischen den Typen unterscheiden.

Beginnen Sie mit dem Modellierungsprozess, indem Sie die Typen mit Labels modellieren. In den folgenden Szenarien können Sie Properties verwenden.

Schemaverwaltung verbessern

Wenn Ihr Graph viele verschiedene Knoten- und Kantentypen hat, kann die Verwaltung einer separaten Eingabetabelle für jeden schwierig werden. Um die Schemaverwaltung zu vereinfachen, modellieren Sie den Typ als Property.

Modelltypen in einer Property, um häufig wechselnde Typen zu verwalten

Wenn Sie Typen als Labels modellieren, müssen Sie das Schema ändern, wenn Sie Typen hinzufügen oder entfernen möchten. Wenn Sie innerhalb kurzer Zeit zu viele Schemaaktualisierungen ausführen, wird die Verarbeitung der anstehenden Schemaaktualisierungen in Spanner möglicherweise drosselt. Weitere Informationen finden Sie unter Häufigkeit von Schemaaktualisierungen begrenzen.

Wenn Sie das Schema häufig ändern müssen, empfehlen wir, den Typ in einer Property zu modellieren, um Einschränkungen bei der Häufigkeit von Schemaaktualisierungen zu umgehen.

Abfragen beschleunigen

Wenn das Knoten- oder Kantenmuster auf mehrere Labels verweist, können Sie Abfragen mit Modelltypen mit Eigenschaften beschleunigen. Mit der folgenden Beispielabfrage werden alle Instanzen von SavingsAccount und InvestmentAccount gefunden, die zu einem Person gehören. Dabei wird davon ausgegangen, dass Kontotypen mit Labels modelliert sind:

GRAPH FinGraph
MATCH (:Person {id: 1})-[:Owns]->(acct:SavingsAccount|InvestmentAccount)
RETURN acct.id;

Das Knotenmuster acct verweist auf zwei Labels. Wenn es sich um eine leistungskritische Abfrage handelt, sollten Sie Account mithilfe einer Property modellieren. Dieser Ansatz kann zu einer besseren Abfrageleistung führen, wie das folgende Abfragebeispiel zeigt. Wir empfehlen, beide Abfragen zu benchmarken.

GRAPH FinGraph
MATCH (:Person {id: 1})-[:Owns]->(acct:Account)
WHERE acct.type IN ("Savings", "Investment")
RETURN acct.id;

Speichern Sie den Typ im Knotenelementschlüssel, um Abfragen zu beschleunigen

Wenn Sie Abfragen mit Filtern nach dem Knotentyp beschleunigen möchten, wenn ein Knotentyp mit einem Attribut modelliert wird und sich der Typ während der Lebensdauer des Knotens nicht ändert, gehen Sie so vor:

  1. Fügen Sie die Property als Teil des Knotenelementschlüssels ein.
  2. Fügen Sie den Knotentyp in die Eingabetabelle für Kanten ein.
  3. Fügen Sie den Knotentyp in die Schlüssel für die Kantenreferenzen ein.

Im folgenden Beispiel wird diese Optimierung auf den Knoten Account und die Kante AccountTransferAccount angewendet.

CREATE TABLE Account (
  type             STRING(MAX) NOT NULL,
  id               INT64 NOT NULL,
  create_time      TIMESTAMP,
) PRIMARY KEY (type, id);

CREATE TABLE AccountTransferAccount (
  type             STRING(MAX) NOT NULL,
  id               INT64 NOT NULL,
  to_type          STRING(MAX) NOT NULL,
  to_id            INT64 NOT NULL,
  amount           FLOAT64,
  create_time      TIMESTAMP NOT NULL,
  order_number     STRING(MAX),
) PRIMARY KEY (type, id, to_type, to_id),
  INTERLEAVE IN PARENT Account ON DELETE CASCADE;

CREATE PROPERTY GRAPH FinGraph
  NODE TABLES (
    Account
  )
  EDGE TABLES (
    AccountTransferAccount
      SOURCE KEY (type, id) REFERENCES Account
      DESTINATION KEY (to_type, to_id) REFERENCES Account
  );

TTL für Knoten und Kanten konfigurieren

Die Gültigkeitsdauer (Time to Live, TTL) von Spanner ist ein Mechanismus, der das automatische Ablaufen und Entfernen von Daten nach einem bestimmten Zeitraum unterstützt. Dieser Speicher wird häufig für Daten mit begrenzter Lebensdauer oder Relevanz verwendet, z. B. Sitzungsinformationen, temporäre Caches oder Ereignisprotokolle. In diesen Fällen trägt die TTL dazu bei, die Datenbankgröße und ‑leistung zu erhalten.

Im folgenden Beispiel werden Konten 90 Tage nach Schließung mithilfe der TTL gelöscht:

CREATE TABLE Account (
  id               INT64 NOT NULL,
  create_time      TIMESTAMP,
  close_time       TIMESTAMP,
) PRIMARY KEY (id),
  ROW DELETION POLICY (OLDER_THAN(close_time, INTERVAL 90 DAY));

Wenn die Knotentabelle eine TTL und eine Kantentabelle enthält, die miteinander verschränkt sind, muss die Verschränkung mit ON DELETE CASCADE definiert werden. Wenn die Knotentabelle eine TTL hat und über einen Fremdschlüssel von einer Kantentabelle referenziert wird, muss der Fremdschlüssel entweder mit ON DELETE CASCADE definiert werden, um die referenzielle Integrität beizubehalten, oder als informativer Fremdschlüssel, um das Vorhandensein von in der Luft hängenden Kanten zu ermöglichen.

Im folgenden Beispiel wird AccountTransferAccount bis zu zehn Jahre lang gespeichert, während ein Konto aktiv bleibt. Wenn ein Konto gelöscht wird, wird auch der Übertragungsverlauf gelöscht.

CREATE TABLE AccountTransferAccount (
  id               INT64 NOT NULL,
  to_id            INT64 NOT NULL,
  amount           FLOAT64,
  create_time      TIMESTAMP NOT NULL,
  order_number     STRING(MAX),
) PRIMARY KEY (id, to_id),
  INTERLEAVE IN PARENT Account ON DELETE CASCADE,
  ROW DELETION POLICY (OLDER_THAN(create_time, INTERVAL 3650 DAY));

Knoten- und Kanten-Eingabetabellen zusammenführen

Sie können dieselbe Eingabetabelle verwenden, um mehrere Knoten und Kanten in Ihrem Schema zu definieren.

In den folgenden Beispieltabellen haben die Account-Knoten einen zusammengesetzten Schlüssel (owner_id, account_id). Es gibt eine implizite Kantendefinition: Der Knoten Person mit dem Schlüssel (id) ist Eigentümer des Knotens Account mit dem zusammengesetzten Schlüssel (owner_id, account_id), wenn id = owner_id ist.

CREATE TABLE Person (
  id INT64 NOT NULL,
) PRIMARY KEY (id);

-- Assume each account has exactly one owner.
CREATE TABLE Account (
  owner_id INT64 NOT NULL,
  account_id INT64 NOT NULL,
) PRIMARY KEY (owner_id, account_id);

In diesem Fall können Sie den Account-Knoten und die PersonOwnAccount-Kante mithilfe der Eingabetabelle Account definieren, wie im folgenden Schemabeispiel gezeigt. Damit alle Elementtabellennamen eindeutig sind, wird der Kantenentitätstabelle im Beispiel der Alias Owns zugewiesen.

CREATE PROPERTY GRAPH FinGraph
  NODE TABLES (
    Person,
    Account
  )
  EDGE TABLES (
    Account AS Owns
      SOURCE KEY (owner_id) REFERENCES Person
      DESTINATION KEY (owner_id, account_id) REFERENCES Account
  );

Nächste Schritte