Best Practices für das Entwerfen eines Spanner-Graphschemas

In diesem Dokument wird beschrieben, wie Sie effiziente Abfragen erstellen, indem Sie Best Practices für das Entwerfen von Spanner Graph-Schemas anwenden. Sie können Ihr Schemadesign iterativ verbessern. Wir empfehlen daher, zuerst kritische Abfragemuster zu ermitteln, um Ihr Schemadesign zu optimieren.

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

Kantenübergang optimieren

Edge Traversal (Kantendurchlauf) ist der Prozess, bei dem ein Graph durchlaufen wird, indem seinen Kanten gefolgt wird. Dabei wird an einem bestimmten Knoten begonnen und entlang verbundener Kanten zu anderen Knoten bewegt. Die Richtung der Kante wird durch das Schema definiert. Das Durchlaufen von Kanten ist ein grundlegender Vorgang in Spanner Graph. Daher ist die Verbesserung der Effizienz des Durchlaufens von Kanten entscheidend für die Leistung Ihrer Anwendung.

Sie können eine Kante in zwei Richtungen durchlaufen:

  • Vorwärtskanten-Traversal: Folgt ausgehenden Kanten des Quellknotens.

  • Reverse Edge Traversal (Rückwärtskanten-Traversal): Folgt eingehenden Kanten des Zielknotens.

Die folgende Beispielabfrage führt für eine Person eine Vorwärtskantentraversierung von Owns-Kanten durch:

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

Mit der folgenden Beispielabfrage wird für ein Konto ein Reverse-Edge-Traversal von Owns-Kanten ausgeführt:

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

Durch Interleaving die Traversierung der Vorwärtskante optimieren

Um die Leistung der Vorwärtskanten-Traversierung zu verbessern, verschränken Sie die Kanten-Eingabetabelle mit der Eingabetabelle des Quellknotens, um Kanten mit Quellknoten zu platzieren. Die Verschränkung ist eine Speicheroptimierungstechnik in Spanner, bei der Zeilen der untergeordneten Tabelle physisch mit den entsprechenden übergeordneten Zeilen im Speicher platziert 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;

Reverse-Edge-Traversal mit Fremdschlüssel optimieren

Um Reverse-Kanten effizient zu durchlaufen, erstellen Sie eine erzwungene Fremdschlüsselbeschränkung zwischen der Kante und dem Zielknoten. Dieser erzwungene Fremdschlüssel erstellt einen sekundären Index für die Kante, die mit den Zielknotenschlüsseln versehen ist. Der sekundäre Index wird bei der Ausführung von Abfragen 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;

Reverse-Edge-Traversal mit sekundärem Index optimieren

Wenn Sie keinen erzwungenen Fremdschlüssel für den Edge erstellen möchten, z. B. aufgrund der strengen Datenintegrität, die er erzwingt, können Sie direkt einen sekundären Index für die 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 AccountOwnedByPerson
ON PersonOwnAccount (account_id), INTERLEAVE IN Account;

Mit INTERLEAVE IN wird eine Datenlokalitätsbeziehung zwischen dem sekundären Index und der Tabelle deklariert, in die er verschachtelt ist (Account im Beispiel). Beim Interleaving werden Zeilen des sekundären Index AccountOwnedByPerson zusammen mit den entsprechenden Zeilen der Tabelle Account gespeichert. Weitere Informationen zum Verschachteln finden Sie unter Über- und untergeordnete Tabellenbeziehungen. Weitere Informationen zum Verschachteln von Indexen finden Sie unter Indexe und Verschachtelung.

Edge-Traversal mit informativen Fremdschlüsseln optimieren

Wenn in Ihrem Szenario Engpässe bei der Schreibgeschwindigkeit auftreten, die durch erzwungene Fremdschlüssel verursacht werden, z. B. wenn Sie häufig Hubknoten aktualisieren, die viele verbundene Kanten haben, sollten Sie informative Fremdschlüssel verwenden. Wenn Sie informative Fremdschlüssel für die Referenzspalten einer Edge-Tabelle verwenden, kann der Query-Optimierer redundante Knotentabellenscans entfernen. Da für informative Fremdschlüssel jedoch keine sekundären Indexe in der Edge-Tabelle erforderlich sind, wird die Geschwindigkeit von Suchvorgängen nicht verbessert, wenn in einer Abfrage versucht wird, Edges anhand von Endknoten zu finden. Weitere Informationen finden Sie unter Vergleich von Fremdschlüsseltypen.

Wenn Ihre Anwendung keine referenzielle Integrität garantieren kann, kann die Verwendung von informativen Fremdschlüsseln zur Abfrageoptimierung zu falschen Abfrageergebnissen führen.

Im folgenden Beispiel wird eine Tabelle mit einem informativen Fremdschlüssel für die 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 nicht möglich ist, können Sie beide Edge-Referenzen mit informativen Fremdschlüsseln markieren, 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 nicht verbundene Kante ist eine Kante, die weniger als zwei Knoten verbindet. Eine freihängende Kante 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 ihren Knoten zu verknüpfen.

Das Verhindern von nicht verbundenen Kanten bietet folgende Vorteile:

  • Erzwingt die Integrität der Diagrammstruktur.
  • Verbessert die Abfrageleistung, da der zusätzliche Aufwand zum Herausfiltern von Kanten vermieden wird, bei denen keine Endpunkte vorhanden sind.

Verwaiste Kanten mit referenziellen Einschränkungen nicht zulassen

Wenn Sie verhindern möchten, dass Kanten ohne Verbindung entstehen, geben Sie Einschränkungen für beide Endpunkte an:

  • Verschachteln Sie die Eingabetabelle für Kanten in die Eingabetabelle für Quellknoten. So wird sichergestellt, dass der Quellknoten einer Kante immer vorhanden ist.
  • Erstellen Sie eine erzwungene Fremdschlüsseleinschränkung für Kanten, um sicherzustellen, dass 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;

Mit ON DELETE CASCADE Kanten beim Löschen eines Knotens automatisch entfernen

Wenn Sie Interleaving oder einen erzwungenen Fremdschlüssel verwenden, um verwaiste Kanten zu verhindern, verwenden Sie die ON DELETE-Klausel, um das Verhalten zu steuern, wenn Sie einen Knoten mit Kanten löschen möchten, die noch angehängt sind. Weitere Informationen finden Sie unter Kaskadierendes Löschen für verschränkte Tabellen und Fremdschlüsselaktionen.

Sie können ON DELETE auf folgende Arten verwenden:

  • ON DELETE NO ACTION (oder Auslassen der ON DELETE-Klausel): 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.

Kaskadierendes Löschen 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 des zu löschenden Knotens 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 in den zu löschenden Knoten Account gelöscht.

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

Wenn die 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 (aber nicht für beide Knoten) definieren.

Um in beiden Fällen verwaiste Kanten zu entfernen, erstellen Sie einen erzwungenen Fremdschlüssel für den Quellknotenverweis der Kante, anstatt die Kanten-Eingabetabelle in die Quellknoten-Eingabetabelle einzufügen.

Wir empfehlen die Interleaving-Technik, um das Durchlaufen der Vorwärtskante zu optimieren. Prüfen Sie vor dem Fortfahren, wie sich die Änderung auf Ihre Arbeitslasten auswirkt. 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);

Mit Sekundärindexen nach Knoten- oder Kantenattributen filtern

Sekundärindexe sind für eine effiziente Abfrageverarbeitung unerlässlich. Sie unterstützen schnelle Suchvorgänge für Knoten und Kanten basierend auf bestimmten Attributwerten, ohne dass die gesamte Diagrammstruktur durchlaufen werden muss. Das ist wichtig, wenn Sie mit großen Diagrammen arbeiten, da das Durchlaufen aller Knoten und Kanten sehr ineffizient sein kann.

Filtern von Knoten nach Attribut beschleunigen

Um das Filtern nach Knotenattributen zu beschleunigen, erstellen Sie sekundäre Indexe für Attribute. Mit der folgenden Abfrage werden beispielsweise Konten für einen bestimmten Alias gesucht. Ohne sekundären Index werden alle Account-Knoten gescannt, um die Filterkriterien zu erfüllen.

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 das gefilterte Attribut, 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 Attribute. Weitere Informationen finden Sie unter Indexierung von NULL-Werten deaktivieren.

Traversal der Vorwärtskante mit Filterung nach Kanteneigenschaften beschleunigen

Wenn Sie eine Kante durchlaufen und dabei nach ihren Attributen filtern, können Sie die Abfrage beschleunigen, indem Sie einen sekundären Index für die Kantenattribute erstellen und den Index in den Quellknoten einfügen.

Mit der folgenden Abfrage werden beispielsweise Konten gefunden, die einer bestimmten Person nach einem bestimmten Zeitpunkt 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 Abfrageeffizienz verbessern können, indem Sie einen sekundären Index für die Referenz des Quellknotens (id) und die Kantenattribute (create_time) erstellen. Verschachteln Sie den Index in der Eingabetabelle des Quellknotens, um ihn mit dem Quellknoten zu platzieren.

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 in der Abfrage effizient alle Kanten gefunden werden, die die Bedingung für create_time erfüllen.

Reverse-Edge-Traversal mit Filterung nach Edge-Attributen beschleunigen

Wenn Sie eine umgekehrte Kante durchlaufen und nach ihren Attributen filtern, können Sie die Abfrage beschleunigen, indem Sie einen sekundären Index mit dem Zielknoten und den Kantenattributen zum Filtern erstellen.

Die folgende Beispielabfrage führt eine umgekehrte Kantendurchquerung mit Filterung nach Kanteneigenschaften durch:

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;

Um diese Abfrage mit einem sekundären Index zu beschleunigen, haben Sie folgende Möglichkeiten:

  • Erstellen Sie einen sekundären Index für den Knotenverweis des Edge-Ziels (account_id) und das Edge-Attribut (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 Abfrage-Engine effizient Kanten für account_id finden, die die Bedingung für create_time erfüllen. Wenn jedoch verschiedene Abfragemuster nach unterschiedlichen Attributen filtern, ist für jedes Attribut möglicherweise ein separater Index erforderlich, was zusätzlichen Aufwand bedeutet.

  • Erstellen Sie einen sekundären Index für die Referenz des Zielknotens der Kante (account_id) und speichern Sie die Kanteneigenschaft (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 Attribute gespeichert werden. Bei der Abfrage müssen jedoch alle Kanten des Zielknotens gelesen und dann nach Kantenattributen gefiltert werden.

Sie können diese Ansätze kombinieren, indem Sie die folgenden Richtlinien beachten:

  • Verwenden Sie Edge-Properties in Indexspalten, wenn sie in leistungsrelevanten Abfragen verwendet werden.
  • Fügen Sie Attribute, die in weniger leistungsintensiven Abfragen verwendet werden, in die Spalten für die Speicherung ein.

Knoten- und Kantentypen mit Labels und Attributen modellieren

Knoten- und Kantentypen werden in der Regel mit Labels modelliert. Sie können jedoch auch Eigenschaften verwenden, um Typen zu modellieren. Angenommen, es gibt viele verschiedene Arten von Konten, z. B. BankAccount, InvestmentAccount und RetirementAccount. Sie können die Konten in separaten Eingabetabellen speichern und als separate Labels modellieren oder sie in einer einzelnen Eingabetabelle speichern und eine Property verwenden, um zwischen den Typen zu unterscheiden.

Beginnen Sie mit der Modellierung der Typen mit Labels. In den folgenden Szenarien kann es sinnvoll sein, Properties zu verwenden.

Schemaverwaltung verbessern

Wenn Ihr Diagramm viele verschiedene Knoten- und Kantentypen enthält, kann die Verwaltung einer separaten Eingabetabelle für jeden Typ schwierig werden. Um die Schemabearbeitung zu vereinfachen, modellieren Sie den Typ als Attribut.

Modelltypen in einer Property verwalten, um häufige Änderungen zu berücksichtigen

Wenn Sie Typen als Labels modellieren, müssen Sie das Schema ändern, wenn Sie Typen hinzufügen oder entfernen. Wenn Sie zu viele Schemaaktualisierungen in kurzer Zeit durchführen, kann es sein, dass Spanner die Verarbeitung der in die Warteschlange eingereihten Schemaaktualisierungen 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 Sie Modelltypen mit Attributen verwenden, können Abfragen beschleunigt werden, wenn im Knoten- oder Kantenmuster auf mehrere Labels verwiesen wird. Mit der folgenden Beispielabfrage werden alle Instanzen von SavingsAccount und InvestmentAccount gefunden, die einem Person gehören. Dabei wird davon ausgegangen, dass Kontotypen mit Labels modelliert werden:

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 leistungsrelevante Abfrage handelt, sollten Sie Account mit einer Eigenschaft modellieren. Dieser Ansatz kann die Abfrageleistung verbessern, wie im folgenden Beispiel zu sehen ist. Wir empfehlen, beide Abfragen zu vergleichen.

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.

So beschleunigen Sie Abfragen mit Filterung nach dem Knotentyp, wenn ein Knotentyp mit einem Attribut modelliert wird und sich der Typ während der Lebensdauer des Knotens nicht ändert:

  1. Fügen Sie das Attribut als Teil des Knotenelementschlüssels ein.
  2. Fügen Sie den Knotentyp in die Edge-Eingabetabelle ein.
  3. Nehmen Sie den Knotentyp in die Referenzschlüssel für die Kanten auf.

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) in Spanner ist ein Mechanismus, der das automatische Ablaufen und Entfernen von Daten nach einem bestimmten Zeitraum unterstützt. Dies wird häufig für Daten verwendet, die eine begrenzte Lebensdauer oder Relevanz haben, z. B. Sitzungsinformationen, temporäre Caches oder Ereignisprotokolle. In diesen Fällen trägt die TTL dazu bei, die Datenbankgröße und ‑leistung aufrechtzuerhalten.

Im folgenden Beispiel wird die TTL verwendet, um Konten 90 Tage nach ihrer Schließung zu löschen:

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 verschränkte Kantentabelle hat, muss die Verschachtelung 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 aufrechtzuerhalten, oder als informativer Fremdschlüssel, um die Existenz von verwaisten Kanten zu ermöglichen.

Im folgenden Beispiel wird AccountTransferAccount bis zu zehn Jahre lang gespeichert, solange ein Konto aktiv ist. Wenn ein Konto gelöscht wird, wird auch der Überweisungsverlauf 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 Edge-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 der Eigentümer des Knotens Account mit dem zusammengesetzten Schlüssel (owner_id, account_id), wenn id gleich 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 die Eingabetabelle Account verwenden, um den Knoten Account und die Kante PersonOwnAccount zu definieren, wie im folgenden Schema-Beispiel gezeigt. Damit alle Elementtabellennamen eindeutig sind, wird in diesem Beispiel für die Definition der Edge-Tabelle der Alias Owns verwendet.

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