Übersicht über Diagramme, die aus SQL-Ansichten erstellt wurden

In diesem Dokument erfahren Sie mehr über die Vorteile der Verwendung von SQL-Ansichten zum Erstellen eines Graphen. Dieses Dokument enthält Vorteile des Erstellens von Graphen mit Ansichten, Anforderungen und Überlegungen, die Ihnen bei der Entscheidung helfen, ob Sie Tabellen oder Ansichten zum Erstellen eines Graphen verwenden sollten.

Weitere Informationen zum Erstellen eines Graphen aus Ansichten finden Sie unter Property Graph aus SQL-Ansichten erstellen.

Vorteile der Erstellung von Diagrammen mit Ansichten anstelle von Tabellen

Eine SQL-Ansicht ist eine virtuelle Tabelle, die durch eine SQL-Abfrage definiert wird. In Spanner wird die Abfrage, die eine Ansicht definiert, jedes Mal ausgeführt, wenn eine Abfrage ausgeführt wird, die sich auf die Ansicht bezieht. Spanner-Ansichten sind keine materialisierten Ansichten, da die Ergebnisse der Abfrage, die die Ansicht definiert, nicht als tatsächliche Tabelle im Datenspeicher gespeichert werden. Weitere Informationen finden Sie unter Ansichten – Übersicht. Sie können Diagrammelemente aus SQL-Ansichten erstellen, aber keine Ansicht, die ein Diagramm abfragt.

Ansichten bieten als Abstraktionsebene zwischen Tabellen und einem Diagrammschema mehrere Vorteile, die nicht verfügbar sind, wenn Sie Tabellen zum Erstellen eines Diagramms verwenden.

Anforderungen für die Verwendung von Ansichten zum Erstellen von Diagrammen

Wenn Sie Ansichten zum Erstellen von Diagrammelementen verwenden, müssen Sie die folgenden Anforderungen erfüllen:

Verwenden Sie die KEY-Klausel, wenn Sie ein Grafikelement angeben.

Sie müssen die Spalten, die das Grafikelement eindeutig identifizieren, explizit definieren, wenn Sie Ansichten zum Erstellen eines Knoten- oder Kantenelements verwenden. Verwenden Sie dazu die KEY-Klausel in der Definition des Knoten- oder Kantenelements. Informationen zur Verwendung der KEY-Klausel beim Erstellen eines Grafikelements finden Sie in den Codebeispielen in diesem Dokument und unter Spanner Graph aus einer SQL-Ansicht erstellen.

Eindeutigkeit von Knoten- und Kantenschlüsseln sicherstellen

Jeder Knoten und jede Kante in einem Attributgraphen muss einen eindeutigen Schlüssel haben. Wenn Sie Grafikelemente mithilfe von Ansichten definieren, können Sie auswählen, wie die Eindeutigkeit von Elementschlüsseln überprüft wird:

Strenge Schlüsselvalidierung (Standard)

Standardmäßig prüft Spanner, ob Ansichten, die Knoten- oder Kantentabellen definieren, einem der folgenden Muster entsprechen, um sicherzustellen, dass jeder Knoten oder jede Kante eindeutig ist:

  • Muster 1: Die Ansicht verwendet den Primärschlüssel einer einzelnen Tabelle.

  • Muster 2: Die Ansicht verwendet eine GROUP BY- oder eine SELECT DISTINCT-Klausel.

Sie können andere SQL-Operatoren wie WHERE, HAVING, ORDER BY, LIMIT und TABLESAMPLE in Kombination mit diesen Mustern verwenden. Diese Operatoren filtern oder ordnen die Ergebnisse, ändern aber nicht die zugrunde liegende Eindeutigkeitsgarantie, die die Muster bieten.

Muster 1: Primärschlüssel einer einzelnen Tabelle verwenden

In diesem Muster wählt die Ansicht aus einer einzelnen Tabelle aus und die KEY-Klausel in der Graphdefinition entspricht den Primärschlüsselspalten der Basistabelle. Daher ist jede von der Ansicht erzeugte Knoten- oder Kantenzeile eindeutig.

Im folgenden Beispiel wird eine Teilmenge von Zeilen aus der Tabelle Account ausgewählt. Der Graph KEY(account_id) entspricht dem Primärschlüssel der Tabelle Account, sodass jede von der Ansicht erzeugte Zeile eindeutig ist.

-- Table has PRIMARY KEY(account_id).
CREATE TABLE Account (
  account_id INT64 NOT NULL,
  customer_id INT64 NOT NULL,
  account_type STRING(MAX),
  balance INT64
) PRIMARY KEY(account_id);

-- Pattern 1: View uses the primary key from a single table.
CREATE VIEW SavingAccount
  SQL SECURITY INVOKER AS
    SELECT accnt.account_id, accnt.customer_id, accnt.balance
    FROM Account accnt
    WHERE accnt.account_type = 'saving';

CREATE PROPERTY GRAPH SavingAccountGraph
  NODE TABLES (
    -- The element KEY(account_id) matches the table's primary key.
    SavingAccount KEY(account_id)
  );

Muster 2: GROUP BY- oder SELECT DISTINCT-Klausel verwenden

In diesem Muster verwendet die Abfrage der Ansicht eine GROUP BY- oder eine SELECT DISTINCT-Klausel. Die Spalten in der KEY-Klausel müssen mit den Spalten übereinstimmen, die in diesen Klauseln zur Definition der Eindeutigkeit verwendet werden:

  • Für GROUP BY: Die Spalten der KEY-Klausel müssen mit allen Spalten in der GROUP BY-Klausel übereinstimmen.

  • Für SELECT DISTINCT: Die Spalten der KEY-Klausel müssen mit den Spalten in der SELECT DISTINCT-Liste übereinstimmen.

Beispiel mit GROUP BY:

CREATE TABLE Customer (
  customer_id INT64,
  name STRING(MAX)
) PRIMARY KEY (customer_id);

CREATE TABLE SaleOrder (
  order_id INT64,
  customer_id INT64,
  amount INT64
) PRIMARY KEY (order_id);

CREATE VIEW CustomerOrder
  SQL SECURITY INVOKER AS
    SELECT
      s.order_id,
      ANY_VALUE(c.customer_id) AS customer_id,
      ANY_VALUE(c.name) AS customer_name
    FROM Customer c JOIN SaleOrder s ON c.customer_id = s.customer_id
    GROUP BY s.order_id;

CREATE PROPERTY GRAPH OrderGraph
  NODE TABLES (
    -- The KEY(order_id) matches the GROUP BY column in view definition.
    CustomerOrder KEY(order_id)
  );

Beispiel mit SELECT DISTINCT:

CREATE TABLE SaleOrder (
  order_id INT64,
  customer_id INT64,
  amount INT64
) PRIMARY KEY (order_id);

CREATE VIEW KeyCustomer SQL SECURITY INVOKER AS
  SELECT DISTINCT s.customer_id, s.amount
  FROM SaleOrder s
  WHERE s.amount > 1000;

CREATE PROPERTY GRAPH KeyCustomersGraph
  NODE TABLES (
    -- The KEY(customer_id, amount) matches the DISTINCT columns.
    KeyCustomer KEY(customer_id, amount)
  );

Deaktivierte Schlüsselvalidierung (beliebige SQL-Abfrage)

Wenn Ihre Ansicht eine Abfrage verwendet, die nicht Muster 1 oder Muster 2 entspricht, z. B. eine Abfrage, die Tabellen ohne eine GROUP BY- oder SELECT DISTINCT-Klausel verknüpft, können Sie die Validierung von Elementschlüsseln deaktivieren, indem Sie die Grafikoption validate_element_key_uniqueness = false festlegen.

Standardmäßig ist validate_element_key_uniqueness auf true festgelegt. Wenn der Wert auf false gesetzt ist, validiert Spanner die Abfragedefinition der Ansicht nicht, wenn das Schema erstellt wird. Sie können eine beliebige SQL-Abfrage in der Ansicht verwenden. Sie müssen jedoch darauf achten, dass die in der KEY-Klausel angegebenen Spalten eindeutige Werte für jede Knoten- oder Kantenzeile enthalten.

Im folgenden Beispiel wird eine Ansicht mit dem Namen CustomerOrderTrusted definiert, die die Tabellen Customer und SaleOrder ohne GROUP BY-Klausel verknüpft. Da jeder Kundenauftrag eindeutig ist, bleibt die Eindeutigkeit von order_id in den Ansichtsergebnissen erhalten, wenn SaleOrder mit Customer verknüpft wird. Da die Abfrage jedoch einen JOIN verwendet und nicht Muster 1 oder Muster 2 folgt, kann Spanner die Eindeutigkeit nicht syntaktisch prüfen.

Wenn Sie KEY(order_id) angeben und validate_element_key_uniqueness = false in der OPTIONS-Klausel festlegen, können Sie den Property-Graphen definieren, ohne die Ansichtsabfrage zu ändern:

-- View uses a JOIN without GROUP BY or DISTINCT.
CREATE VIEW CustomerOrderTrusted
  SQL SECURITY INVOKER AS
    SELECT
      s.order_id,
      c.customer_id,
      c.name AS customer_name
    FROM Customer c JOIN SaleOrder s ON c.customer_id = s.customer_id;

-- Property graph disables element key uniqueness validation.
CREATE PROPERTY GRAPH OrderGraphTrusted
  NODE TABLES (
    CustomerOrderTrusted
      KEY(order_id)
      LABEL CustomerOrder PROPERTIES(
        order_id,
        customer_id,
        customer_name)
  ) OPTIONS (validate_element_key_uniqueness = false);

Flüchtige Spalten aktivieren, wenn Ansichten Remote-Funktionen verwenden

Sie können einen Property-Graphen für eine Ansicht definieren, die eine Remote-Funktion (LANGUAGE REMOTE) aufruft, indem Sie allow_view_with_volatile_column = true in der OPTIONS-Klausel der CREATE PROPERTY GRAPH-Anweisung festlegen.

Standardmäßig können Sie in Spanner keinen Eigenschaftsgraphen für Ansichten mit flüchtigen Spalten (allow_view_with_volatile_column = false) definieren. Eine Ansichtsspalte ist flüchtig, wenn ihr Ausdruck eine flüchtige Funktion aufruft. Eine Funktion ist flüchtig, wenn sich ihr Rückgabewert auch innerhalb einer einzelnen Anweisungsausführung mit denselben Argumenten ändern kann, z. B. eine Remote-Funktion (NOT DETERMINISTIC). Jede Flüchtigkeit im Definitionstext einer Ansicht, z. B. in einer JOIN-Bedingung oder WHERE-Klausel, macht auch alle projizierten Spalten in der Ansicht flüchtig. Ein Codebeispiel finden Sie unter Attribute mit Remote-Funktionen berechnen.

Überlegungen bei der Verwendung von Ansichten

Wenn Sie Ansichten zum Definieren von Diagrammelementen verwenden, können Ihnen die folgenden Informationen beim Entwerfen und Implementieren eines effektiven Diagramms helfen:

Leistung von Attributgrafikabfragen

Wenn Sie Grafikelemente für Ansichten definieren, die Datentransformationen ausführen (z. B. GROUP BY-, UNNEST- oder JOIN-Vorgänge), sollten Sie die Abfrageleistung für Ihren Anwendungsfall sorgfältig bewerten. Denken Sie daran, dass Spanner die Abfragedefinition einer Ansicht jedes Mal ausführt, wenn eine Abfrage einen Elementmusterabgleich durchführt.

Optimierung des Graphschemas

Wenn Sie Ansichten zum Definieren von Diagrammelementen verwenden, sind einige Optimierungen des Diagrammschemas möglicherweise weniger effektiv als wenn Sie Tabellen zum Definieren von Diagrammelementen verwenden.

Ansichten, die den Primärschlüssel einer einzelnen Tabelle projizieren

Wenn eine Ansicht eine Projektion aus einer einzelnen Basistabelle ist, bleiben alle Optimierungen an dieser zugrunde liegenden Tabelle für Diagrammabfragen wirksam. Wenn Sie beispielsweise die folgenden Techniken auf Basistabellen anwenden, bietet das ähnliche Leistungsvorteile für Diagrammelemente, die für solche Ansichten definiert sind:

Mit der GROUP BY- oder DISTINCT-Klausel definierte Ansichten

Ansichten, die Aggregationen wie GROUP BY, SELECT DISTINCT oder andere komplexe Transformationen ausführen, verlieren die direkte Beziehung zur zugrunde liegenden Tabellenstruktur. Aus diesem Grund bieten Schemaoptimierungen für die Basistabellen möglicherweise nicht dieselben Leistungsvorteile für Diagrammabfragen, die auf den Ansichten ausgeführt werden. Prüfen Sie die Abfrageleistung für Ihren Anwendungsfall sorgfältig, wenn Ihre Ansichten komplexe Aggregationen ausführen.

Datenänderung mit ansichtsbasierten Diagrammen

Ansichten werden nicht materialisiert. Das bedeutet, dass die Ergebnisse der Abfrage, die die Ansicht definiert, nicht als Tabelle im Datenspeicher gespeichert werden. Außerdem haben sie Lesezugriff. Wenn Sie Knoten oder Kanten in einem aus Ansichten erstellten Graphen einfügen, aktualisieren oder löschen möchten, müssen Sie die Daten in den Tabellen ändern, die zum Erstellen der Ansichten verwendet wurden.

Fehlerbehandlung für Diagramme, um die Datenintegrität zu gewährleisten

Wenn Sie Ansichten zum Definieren von Diagrammelementen verwenden, erzwingen Sie die Datenintegrität (z. B. Datentypen) für die zugrunde liegenden Basistabellen. Andernfalls sind die Daten in den Basistabellen möglicherweise ungültig und Abfragen für den ansichtsbasierten Graphen schlagen zur Laufzeit fehl.

Wenn Sie beispielsweise von einem schemalosen zu einem formalisierten Graphen wechseln, verwenden Sie CHECK-Einschränkungen, um Daten in Ihren Basistabellen (GraphNode und GraphEdge) zu validieren. Der folgende Code wendet diese Einschränkungen innerhalb der JSON-Attribute an, um die Datenintegrität an der Quelle zu gewährleisten und Laufzeitabfragefehler zu vermeiden.

-- Enforce that the 'name' property exists for nodes with the 'person' label.
ALTER TABLE GraphNode
ADD CONSTRAINT NameMustExistForPersonConstraint
CHECK (IF(label = 'person', properties.name IS NOT NULL, TRUE));

-- Enforce that the 'name' property is a string for nodes with the 'person' label.
ALTER TABLE GraphNode
ADD CONSTRAINT PersonNameMustBeStringTypeConstraint
CHECK (IF(label = 'person', JSON_TYPE(properties.name) = 'string', TRUE));

Nächste Schritte