Best Practices für das Entwerfen eines Spanner-Graphschemas

In diesem Dokument werden Best Practices für das Entwerfen eines Spanner Graph-Schemas beschrieben. Der Schwerpunkt liegt dabei auf effizienten Abfragen, optimierter Kantendurchquerung und effektiven Datenverwaltungstechniken.

Informationen zum Design von Spanner-Schemas (nicht Spanner Graph-Schemas) finden Sie unter Best Practices für Schemadesign.

Schemadesign auswählen

Das Schemadesign wirkt sich auf die Leistung des Diagramms aus. Die folgenden Themen helfen Ihnen bei der Auswahl einer effektiven Strategie.

Schematisierte und schemalose Designs

  • Bei einem schematisierten Design wird die Graphdefinition im Spanner Graph-Schema gespeichert. Das ist für stabile Graphen mit seltenen Definitionsänderungen geeignet. Das Schema erzwingt die Graphdefinition und Attribute unterstützen alle Spanner-Datentypen.

  • Bei einem schemalosen Design wird die Graphdefinition aus den Daten abgeleitet. Das bietet mehr Flexibilität, ohne dass Schemaänderungen erforderlich sind. Dynamische Labels und Eigenschaften werden nicht standardmäßig erzwungen. Eigenschaften müssen gültige JSON-Werte sein.

Im Folgenden werden die wichtigsten Unterschiede zwischen der schemabasierten und der schemalosen Datenverwaltung zusammengefasst. Berücksichtigen Sie auch Ihre Diagrammabfragen, um zu entscheiden, welcher Schematyp verwendet werden soll.

Funktion Schematisierte Datenverwaltung Schemalose Datenverwaltung
Grafikdefinition speichern Die Diagrammdefinition wird im Spanner Graph-Schema gespeichert. Die Graphdefinition ist aus den Daten ersichtlich. Spanner Graph untersucht die Daten jedoch nicht, um die Definition abzuleiten.
Aktualisieren der Diagrammdefinition Erfordert eine Änderung des Spanner Graph-Schemas. Geeignet, wenn die Definition klar definiert ist und sich nur selten ändert. Es ist keine Änderung des Spanner Graph-Schemas erforderlich.
Grafikdefinition erzwingen Ein Property-Graph-Schema erzwingt die zulässigen Knotentypen für eine Kante. Außerdem werden die zulässigen Attribute und Attributtypen eines Knoten- oder Kantentyps im Diagramm erzwungen. Wird standardmäßig nicht erzwungen. Mit Prüfeinschränkungen können Sie die Datenintegrität von Labels und Properties erzwingen.
Attributdatentypen Unterstützt alle Spanner-Datentypen, z. B. timestamp. Dynamische Eigenschaften müssen einen gültigen JSON-Wert haben.

Schemaentwurf basierend auf Diagrammabfragen auswählen

Schematisierte und schemalose Designs bieten in der Regel eine vergleichbare Leistung. Die Ausnahme ist, wenn in Abfragen quantifizierte Pfadmuster verwendet werden, die mehrere Knoten- oder Kantentypen umfassen. In diesem Fall bietet ein schemaloses Design eine bessere Leistung. Das liegt daran, dass bei schemalosen Designs alle Daten in einzelnen Knoten- und Kantentabellen gespeichert werden, wodurch Tabellenscans minimiert werden. Bei schematisierten Designs werden dagegen separate Tabellen für jeden Knoten- und Kantentyp verwendet. Für Abfragen, die mehrere Typen umfassen, müssen Daten aus allen entsprechenden Tabellen gescannt und kombiniert werden.

Im Folgenden finden Sie Beispielabfragen, die gut mit schemalosen Designs funktionieren, sowie eine Beispielabfrage, die mit beiden Designs funktioniert:

Schemaloses Design

Die folgenden Abfragen funktionieren mit einem schemalosen Design besser, da sie quantifizierte Pfadmuster verwenden, die mit mehreren Arten von Knoten und Kanten übereinstimmen können:

  • Das quantifizierte Pfadmuster dieser Abfrage verwendet mehrere Kantentypen (Transfer oder Withdraw) und gibt keine Zwischenknotentypen für Pfade an, die länger als ein Hop sind.

    GRAPH FinGraph
    MATCH p = (:Account {id:1})-[:Transfer|Withdraw]->{1,3}(:Account)
    RETURN TO_JSON(p) AS p;
    
  • Mit dem quantifizierten Pfadmuster dieser Abfrage werden Pfade mit ein bis drei Hops zwischen Person- und Account-Knoten gefunden, wobei mehrere Kantentypen (Owns oder Transfers) verwendet werden, ohne dass für längere Pfade Zwischeknotentypen angegeben werden. So können Pfade Zwischenknoten verschiedener Typen durchlaufen. Beispiel: (:Person)-[:Owns]->(:Account)-[:Transfers]->(:Account).

    GRAPH FinGraph
    MATCH p = (:Person {id:1})-[:Owns|Transfers]->{1,3}(:Account)
    RETURN TO_JSON(p) AS p;
    
  • Mit dieser Abfrage werden Pfade mit ein bis drei Hops zwischen Account-Knoten über Kanten vom Typ Owns in beliebiger Richtung (-[:Owns]-) gefunden. Da Pfade Kanten in beide Richtungen durchlaufen können und Zwischenknoten nicht angegeben sind, kann ein Pfad mit zwei Hops Knoten unterschiedlicher Typen durchlaufen. Beispiel: (:Account)-[:Owns]-(:Person)-[:Owns]-(:Account).

    GRAPH FinGraph
    MATCH p = (:Account {id:1})-[:Owns]-{1,3}(:Account)
    RETURN TO_JSON(p) AS p;
    

Beide Designs

Die folgende Abfrage ist sowohl bei schematisierten als auch bei schemalosen Designs vergleichbar. Der quantifizierte Pfad (:Account)-[:Transfer]->{1,3}(:Account) umfasst einen Knotentyp (Account) und einen Kantentyp (Transfer). Da der Pfad nur einen Knotentyp und einen Kantentyp umfasst, ist die Leistung für beide Designs vergleichbar. Auch wenn Zwischenknoten nicht explizit gekennzeichnet sind, werden sie durch das Muster auf Account-Knoten beschränkt. Der Knoten Person befindet sich außerhalb dieses quantifizierten Pfads.

GRAPH FinGraph
MATCH p = (:Person {id:1})-[:Owns]->(:Account)-[:Transfer]->{1,3}(:Account)
RETURN TO_JSON(p) AS p;

Leistung von Spanner Graph-Schemas optimieren

Nachdem Sie sich für ein schematisiertes oder schemaloses Spanner Graph-Schema entschieden haben, können Sie die Leistung auf folgende Weise optimieren:

Kantenübergang optimieren

Beim Edge-Traversal wird ein Graph durchlaufen, indem seinen Kanten gefolgt wird. Dabei wird an einem bestimmten Knoten begonnen und entlang verbundener Kanten zu anderen Knoten bewegt. Das Schema definiert die Richtung der Kante. Das Durchlaufen von Kanten ist ein grundlegender Vorgang in Spanner Graph. Wenn Sie die Effizienz des Durchlaufens von Kanten verbessern, kann sich die Leistung Ihrer Anwendung erheblich steigern.

Sie können eine Kante in zwei Richtungen durchlaufen:

  • Beim Vorwärtskanten-Traversal werden die ausgehenden Kanten des Quellknotens durchlaufen.
  • Beim Rückwärts-Edge-Traversal werden eingehende Kanten des Zielknotens berücksichtigt.

Beispiele für Abfragen zum Vorwärts- und Rückwärts-Edge-Traversal

Die folgende Beispielabfrage führt eine Vorwärtskantendurchquerung von Owns-Kanten für eine bestimmte Person aus:

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

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

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

Traversal der Vorwärtskante optimieren

Um die Leistung der Vorwärtskanten-Traversierung zu verbessern, optimieren Sie die Traversierung von der Quelle zur Kante und von der Kante zum Ziel.

  • Um die Quell-zu-Edge-Traversierung zu optimieren, verschachteln Sie die Edge-Eingabetabelle mit der INTERLEAVE IN PARENT-Klausel in die Eingabetabelle des Quellknotens. Die Verschachtelung ist eine Speicheroptimierungstechnik in Spanner, bei der Zeilen untergeordneter Tabellen zusammen mit den entsprechenden übergeordneten Zeilen im Speicher platziert werden. Weitere Informationen zum Interleaving finden Sie unter Schemas – Übersicht.

  • Um die Traversierung von Edge zum Ziel zu optimieren, erstellen Sie eine Fremdschlüsselbeschränkung zwischen dem Edge- und dem Zielknoten
    . Dadurch wird die Einschränkung „Edge-to-Destination“ erzwungen, was die Leistung verbessern kann, da keine Zieltabellenscans mehr erforderlich sind. Wenn erzwungene Fremdschlüssel zu Engpässen bei der Schreibgeschwindigkeit führen (z. B. beim Aktualisieren von Hubknoten), verwenden Sie stattdessen einen informational foreign key.

Die folgenden Beispiele zeigen, wie Sie Interleaving mit einer erzwungenen und einer informativen Fremdschlüsselbeschränkung verwenden.

Erzwungener Fremdschlüssel

In diesem Beispiel für eine Edge-Tabelle wird PersonOwnAccount für Folgendes verwendet:

  • Wird in die Quellknotentabelle Person eingefügt.

  • Erstellt einen erzwungenen Fremdschlüssel für die Zielknotentabelle Account.

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

CREATE TABLE Account (
  id               INT64 NOT NULL,
  create_time      TIMESTAMP,
  close_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;

Informativer Fremdschlüssel

In diesem Beispiel für eine Edge-Tabelle wird PersonOwnAccount für Folgendes verwendet:

  • Wird in die Quellknotentabelle Person eingefügt.

  • Erstellt einen informativen Fremdschlüssel für die Zielknotentabelle Account.

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

CREATE TABLE Account (
  id               INT64 NOT NULL,
  create_time      TIMESTAMP,
  close_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) NOT ENFORCED
) PRIMARY KEY (id, account_id),
  INTERLEAVE IN PARENT Person ON DELETE CASCADE;

Rückwärtskanten-Traversal optimieren

Optimieren Sie die Rückwärtskanten-Traversierung, es sei denn, Ihre Abfragen verwenden nur die Vorwärts-Traversierung, da Abfragen mit Rückwärts- oder bidirektionaler Traversierung häufig sind.

So optimieren Sie die Rückwärtsbewegung von Kanten:

  • Erstellen Sie einen sekundären Index für die Edge-Tabelle.

  • Verschachteln Sie den Index in der Eingabetabelle des Zielknotens, um die Kanten mit den Zielknoten zu platzieren.

  • Speichern Sie die Kanteneigenschaften im Index.

In diesem Beispiel wird ein sekundärer Index gezeigt, mit dem die Rückwärtsbewegung von Kanten für die Kantentabelle PersonOwnAccount optimiert wird:

  • Mit der INTERLEAVE IN-Klausel werden die Indexdaten mit der Zielknotentabelle Account zusammengeführt.

  • Mit der STORING-Klausel werden Kanteneigenschaften im Index gespeichert.

Weitere Informationen zum Verschachteln von Indexen finden Sie unter Indexe und Verschachtelung.

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)
STORING (create_time),
INTERLEAVE IN Account;

Sekundäre Indexe zum Filtern von Attributen verwenden

Ein sekundärer Index ermöglicht das effiziente Suchen von Knoten und Kanten auf Grundlage bestimmter Attributwerte. Durch die Verwendung eines Index wird ein vollständiger Tabellenscan vermieden. Das ist besonders bei großen Grafiken nützlich.

Filtern von Knoten nach Attribut beschleunigen

Die folgende Abfrage sucht nach Konten für einen bestimmten Alias. Da kein sekundärer Index verwendet wird, müssen alle Account-Knoten gescannt werden, um die passenden Ergebnisse zu finden:

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

Erstellen Sie einen sekundären Index für das gefilterte Attribut in Ihrem Schema, um den Filtervorgang zu beschleunigen:

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

Filtern von Kanten nach Attributen beschleunigen

Sie können einen sekundären Index verwenden, um die Leistung beim Filtern von Kanten anhand von Property-Werten zu verbessern.

Vorwärtskanten-Traversal

Ohne einen sekundären Index muss diese Abfrage alle Kanten einer Person scannen, um die Kanten zu finden, die dem create_time-Filter entsprechen:

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;

Mit dem folgenden Code wird die Abfrageeffizienz verbessert, indem ein sekundärer Index für die Referenz des Quellknotens der Kante (id) und die Kanteneigenschaft (create_time) erstellt wird. In der Abfrage wird der Index auch als verschachteltes untergeordnetes Element der Eingabetabelle des Quellknotens definiert, wodurch der Index mit dem Quellknoten collocated wird.

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;

Kantenrückwärtslauf

Ohne sekundären Index muss bei der folgenden Abfrage zum Durchlaufen von Kanten in umgekehrter Richtung zuerst jede Kante gelesen werden, bevor die Person gefunden werden kann, die das angegebene Konto nach dem angegebenen create_time besitzt:

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;

Mit dem folgenden Code wird die Abfrageeffizienz verbessert, indem ein sekundärer Index für die Referenz des Zielknotens der Kante (account_id) und die Kanteneigenschaft (create_time) erstellt wird. In der Abfrage wird der Index auch als verschachteltes untergeordnetes Element der Zielknotentabelle definiert, wodurch der Index mit dem Zielknoten collocated wird.

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 AccountOwnedByPersonByCreateTime
ON PersonOwnAccount (account_id, create_time),
INTERLEAVE IN Account;

Lose Kanten verhindern

Eine Kante, die null oder einen Knoten verbindet, eine dangling edge, kann die Effizienz von Spanner Graph-Abfragen und die Integrität der Diagrammstruktur beeinträchtigen. Eine lose Kante kann auftreten, wenn Sie einen Knoten löschen, ohne die zugehörigen Kanten zu löschen. Eine freie Kante kann auch auftreten, wenn Sie eine Kante erstellen, deren Quell- oder Zielknoten nicht vorhanden ist. Um lose Kanten zu vermeiden, sollten Sie Folgendes in Ihr Spanner Graph-Schema aufnehmen:

Referenzielle Einschränkungen verwenden

Sie können Interleaving und erzwungene Fremdschlüssel für beide Endpunkte verwenden, um verwaiste Kanten zu verhindern. Gehen Sie dazu so vor:

  1. Verschachteln Sie die Eingabetabelle für Kanten in die Eingabetabelle für Quellknoten, damit der Quellknoten einer Kante immer vorhanden ist.

  2. Erstellen Sie eine erzwungene Fremdschlüsseleinschränkung für Kanten, um sicherzustellen, dass der Zielknoten einer Kante immer vorhanden ist. Erzwungene Fremdschlüssel verhindern zwar lose Kanten, machen das Einfügen und Löschen von Kanten jedoch aufwendiger.

Im folgenden Beispiel wird ein erzwungener Fremdschlüssel verwendet und die Eingabetabelle für Kanten wird mit der Klausel INTERLEAVE IN PARENT in die Eingabetabelle für Quellknoten verschachtelt. Die Verwendung eines erzwungenen Fremdschlüssels und das Verschachteln können auch dazu beitragen, die Traversierung von Forward Edges zu optimieren.

  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;

Kanten mit ON DELETE CASCADE löschen

Wenn Sie Interleaving oder einen erzwungenen Fremdschlüssel verwenden, um verwaiste Kanten zu verhindern, verwenden Sie die ON DELETE CASCADE-Klausel in Ihrem Spanner Graph-Schema, um die zugehörigen Kanten eines Knotens in derselben Transaktion zu löschen, in der der Knoten gelöscht wird. Weitere Informationen finden Sie unter Kaskadierendes Löschen für verschränkte Tabellen und Fremdschlüsselaktionen.

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

Die folgenden Beispiele zeigen, wie Sie ON DELETE CASCADE in Ihrem Spanner Graph-Schema verwenden, um verwaiste Kanten zu löschen, wenn Sie einen Quell- oder Zielknoten löschen. In beiden Fällen unterscheiden sich der Typ des gelöschten Knotens und der Typ des Knotens, der über eine Kante mit ihm verbunden ist.

Quellknoten

Verwenden Sie die Verschachtelung, um verwaiste Kanten zu löschen, wenn der Quellknoten gelöscht wird. Im Folgenden wird gezeigt, wie Sie mit Interleaving die ausgehenden Kanten löschen, wenn der Quellknoten (Person) gelöscht wird. Weitere Informationen finden Sie unter Verschachtelte Tabellen erstellen.

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

Zielknoten

Verwenden Sie eine Fremdschlüsseleinschränkung, um verwaiste Kanten zu löschen, wenn der Zielknoten gelöscht wird. Im folgenden Beispiel wird gezeigt, wie ein Fremdschlüssel mit ON DELETE CASCADE in einer Edge-Tabelle verwendet wird, um eingehende Edges zu löschen, wenn der Zielknoten (Account) gelöscht wird:

CONSTRAINT FK_Account FOREIGN KEY(account_id)
  REFERENCES Account(id) ON DELETE CASCADE

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 für den Quell- oder Zielknoten definieren, aber nicht für beide.

Um in diesen Szenarien hängende Kanten zu vermeiden, verschränken Sie die Eingabetabelle des Quellknotens nicht. Erstellen Sie stattdessen zwei erzwungene Fremdschlüssel für die Quell- und Zielknotenreferenzen.

Im folgenden Beispiel wird AccountTransferAccount als Eingabetabelle für Kanten verwendet. Es werden zwei Fremdschlüssel definiert, einer für jeden Endknoten der Übertragungskante, beide mit der Aktion ON DELETE CASCADE.

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

Gültigkeitsdauer (Time to Live, TTL) für Knoten und Kanten konfigurieren

Mit TTL können Sie Daten nach einem bestimmten Zeitraum ablaufen lassen und entfernen. Sie können TTL in Ihrem Schema verwenden, um die Datenbankgröße und ‑leistung zu optimieren, indem Sie Daten entfernen, die nur eine begrenzte Lebensdauer oder Relevanz haben. Sie können beispielsweise festlegen, dass Sitzungsinformationen, temporäre Caches oder Ereignisprotokolle entfernt werden.

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 Sie eine TTL-Richtlinie für eine Knotentabelle definieren, müssen Sie konfigurieren, wie zugehörige Kanten behandelt werden, um unbeabsichtigte verwaiste Kanten zu vermeiden:

  • Für verschränkte Edge-Tabellen:Wenn eine Edge-Tabelle in der Knotentabelle verschränkt ist, können Sie die Verschränkungsbeziehung mit ON DELETE CASCADE definieren. So wird sichergestellt, dass beim Löschen eines Knotens durch TTL auch die zugehörigen verschachtelten Kanten gelöscht werden.

  • Für Edge-Tabellen mit Fremdschlüsseln:Wenn in einer Edge-Tabelle mit einem Fremdschlüssel auf die Knotentabelle verwiesen wird, haben Sie zwei Möglichkeiten:

    • Wenn Sie Kanten automatisch löschen möchten, wenn der referenzierte Knoten durch TTL gelöscht wird, verwenden Sie ON DELETE CASCADE für den Fremdschlüssel. Dadurch bleibt die referenzielle Integrität erhalten.
    • Wenn Kanten auch nach dem Löschen des referenzierten Knotens erhalten bleiben sollen (wodurch eine lose Kante entsteht), definieren Sie den Fremdschlüssel als Informationsfremdschlüssel.

Im folgenden Beispiel unterliegt die AccountTransferAccount-Kanten-Tabelle zwei Richtlinien zum Löschen von Daten:

  • Mit einer TTL-Richtlinie werden Übertragungsdatensätze gelöscht, die älter als zehn Jahre sind.
  • Mit der Klausel ON DELETE CASCADE werden alle Übertragungsdatensätze, die mit einer Quelle verknüpft sind, gelöscht, wenn das Konto gelöscht wird.
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

Um Ihr Schema zu optimieren, definieren Sie einen Knoten und seine eingehenden oder ausgehenden Kanten in einer einzelnen Tabelle. Dieser Ansatz bietet folgende Vorteile:

  • Weniger Tabellen: Die Anzahl der Tabellen in Ihrem Schema wird reduziert, was die Datenverwaltung vereinfacht.

  • Verbesserte Abfrageleistung: Es ist kein Durchlauf mehr erforderlich, bei dem Joins für eine separate Edge-Tabelle verwendet werden.

Diese Methode eignet sich gut, wenn der Primärschlüssel einer Tabelle auch eine Beziehung zu einer anderen Tabelle definiert. Wenn die Tabelle Account beispielsweise einen zusammengesetzten Primärschlüssel (owner_id, account_id) hat, kann der Teil owner_id ein Fremdschlüssel sein, der auf die Tabelle Person verweist. Mit dieser Struktur kann in der Tabelle Account sowohl der Knoten Account als auch die eingehende Kante vom Knoten Person dargestellt werden.

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

Sie können die Tabelle Account verwenden, um sowohl den Knoten Account als auch die eingehende Kante Owns zu definieren. Dies wird in der folgenden CREATE PROPERTY GRAPH-Anweisung gezeigt. In der EDGE TABLES-Klausel geben Sie der Tabelle Account den Alias Owns. Das liegt daran, dass jedes Element im Diagrammschema einen eindeutigen Namen haben muss.

  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