Descripción general de los gráficos creados a partir de vistas de SQL

Usa este documento para obtener información sobre los beneficios de usar vistas de SQL para crear un grafo. Este documento incluye los beneficios de crear grafos con vistas, los requisitos, y las consideraciones para ayudarte a decidir si debes usar tablas o vistas para crear un grafo.

Para obtener detalles sobre cómo crear un grafo a partir de vistas, consulta Crea un grafo de propiedades a partir de vistas de SQL.

Beneficios de crear grafos con vistas en lugar de tablas

Una vista de SQL es una tabla virtual definida por una consulta en SQL. En Spanner, la consulta que define una vista se ejecuta cada vez que se ejecuta una consulta que hace referencia a la vista. Las vistas de Spanner no son vistas materializadas porque no almacenan los resultados de la consulta que define la vista como una tabla real en el almacenamiento de datos. Para obtener más información, consulta Descripción general de las vistas. Puedes crear elementos de grafo a partir de vistas de SQL, pero no puedes crear una vista que consulte un grafo.

Las vistas proporcionan varias ventajas como una capa de abstracción entre las tablas y un esquema de grafo que no están disponibles cuando usas tablas para crear un grafo.

Requisitos para usar vistas para crear grafos

Debes seguir estos requisitos cuando uses vistas para crear elementos de grafo:

Usa la cláusula KEY cuando especifiques un elemento de grafo

Debes definir de forma explícita las columnas que identifican de manera única el elemento de grafo cuando usas vistas para crear un nodo o un elemento de arista. Para ello, usa la cláusula KEY en la definición del elemento de nodo o arista. Para obtener información sobre cómo usar la KEY cláusula cuando creas un elemento de grafo, consulta los ejemplos de código en este documento y en Crea un Spanner Graph a partir de una vista de SQL.

Asegúrate de que las claves de nodos y aristas sean únicas

Cada nodo y arista de un grafo de propiedades debe tener una clave única. Cuando defines elementos de grafo con vistas, puedes elegir cómo se verifica la unicidad de la clave del elemento:

Validación estricta de claves (predeterminada)

De forma predeterminada, Spanner verifica que las vistas que definen tablas de nodos o aristas sigan uno de los siguientes patrones para garantizar que cada nodo o arista sea único:

  • Patrón 1: La vista usa la clave primaria de una sola tabla.

  • Patrón 2: La vista usa una GROUP BY o una SELECT DISTINCT cláusula.

Puedes usar otros operadores de SQL, como WHERE, HAVING, ORDER BY,LIMIT y TABLESAMPLE, en combinación con estos patrones. Estos operadores filtran u ordenan los resultados, pero no cambian la garantía de unicidad subyacente que proporcionan los patrones.

Patrón 1: Usa la clave primaria de una sola tabla

En este patrón, la vista selecciona una sola tabla y la cláusula KEY en la definición del grafo coincide con las columnas de clave primaria de la tabla base. Debido a esto, cada fila de nodo o arista que produce la vista es única.

Por ejemplo, lo siguiente selecciona un subconjunto de filas de la tabla Account. El grafo KEY(account_id) coincide con la clave primaria de la tabla Account, lo que garantiza que cada fila que produce la vista sea única.

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

Patrón 2: Usa la cláusula GROUP BY o SELECT DISTINCT

En este patrón, la consulta de la vista usa una cláusula GROUP BY o SELECT DISTINCT. Las columnas de la cláusula KEY deben coincidir con las columnas que usan estas cláusulas para definir la unicidad:

  • Para GROUP BY: Las columnas de la cláusula KEY deben coincidir con todas las columnas de la cláusula GROUP BY.

  • Para SELECT DISTINCT: Las columnas de la cláusula KEY deben coincidir con las columnas de la lista SELECT DISTINCT.

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

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

Validación de claves inhabilitada (cualquier consulta en SQL)

Si tu vista usa una consulta que no sigue el Patrón 1 o el Patrón 2, como una consulta que une tablas sin una cláusula GROUP BY o SELECT DISTINCT, puedes inhabilitar la validación de claves de elementos si estableces la opción de grafo validate_element_key_uniqueness = false.

De forma predeterminada, validate_element_key_uniqueness es true. Cuando se establece en false, Spanner no valida la definición de consulta de la vista en el momento de la creación del esquema. Puedes usar cualquier consulta en SQL en la vista, pero debes asegurarte de que las columnas especificadas en la cláusula KEY contengan valores únicos para cada fila de nodo o arista.

En el siguiente ejemplo, se define una vista llamada CustomerOrderTrusted que une las Customer y SaleOrder tablas sin una cláusula GROUP BY. Debido a que cada pedido de venta es único, unir SaleOrder con Customer conserva la unicidad de order_id en los resultados de la vista. Sin embargo, debido a que la consulta usa un JOIN y no sigue el Patrón 1 ni el Patrón 2, Spanner no puede verificar la unicidad de forma sintáctica.

Si especificas KEY(order_id) y estableces validate_element_key_uniqueness = false en la cláusula OPTIONS, puedes definir el grafo de propiedades sin modificar la consulta de la vista:

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

Consideraciones para cuando usas vistas

Cuando usas vistas para definir elementos de grafo, lo siguiente puede ayudarte a diseñar e implementar un grafo eficaz:

Rendimiento de las consultas de grafos de propiedades

Cuando defines elementos de grafo en vistas que realizan transformaciones de datos (por ejemplo, operaciones GROUP BY, UNNEST o JOIN), evalúa cuidadosamente el rendimiento de las consultas para tu caso de uso. Recuerda que Spanner ejecuta la definición de consulta de una vista cada vez que una consulta realiza la coincidencia de patrones de elementos.

Optimización del esquema de grafo

Cuando usas vistas para definir elementos de grafo, algunas optimizaciones del esquema de grafo pueden ser menos eficaces que cuando usas tablas para definir elementos de grafo.

Vistas que proyectan la clave primaria de una sola tabla

Si una vista es una proyección de una sola tabla base, cualquier optimización en esa tabla subyacente sigue siendo eficaz para las consultas de grafos. Por ejemplo, aplicar las siguientes técnicas a las tablas base proporciona beneficios de rendimiento similares para los elementos de grafo definidos en esas vistas:

Vistas definidas con la cláusula GROUP BY o DISTINCT

Las vistas que realizan agregaciones, como GROUP BY, SELECT DISTINCT o cualquier otra transformación compleja, pierden la relación directa con la estructura de la tabla subyacente. Debido a esto, las optimizaciones de esquema en las tablas base podrían no proporcionar los mismos beneficios de rendimiento para las consultas de grafos que operan en las vistas. Evalúa cuidadosamente el rendimiento de las consultas para tu caso de uso cuando tus vistas realicen agregaciones complejas.

Modificación de datos con grafos basados en vistas

Las vistas no están materializadas, lo que significa que no almacenan los resultados de la consulta que define la vista como una tabla en el almacenamiento de datos y son de solo lectura. Debido a esto, para insertar, actualizar o descartar nodos o aristas en un grafo creado a partir de vistas, debes modificar los datos en las tablas que se usan para crear las vistas.

Manejo de errores de grafos para aplicar la integridad de los datos

Cuando usas vistas para definir elementos de grafo, aplica la integridad de los datos (por ejemplo, aplica tipos de datos) en las tablas base subyacentes. De lo contrario, los datos de las tablas base podrían no ser válidos y provocar que las consultas en tu grafo basado en vistas fallen en el tiempo de ejecución.

Por ejemplo, cuando realizas la transición de un grafo sin esquema a uno formalizado, usa CHECK restricciones para validar los datos en tus tablas base (GraphNode y GraphEdge). El siguiente código aplica estas restricciones dentro de las propiedades JSON para garantizar la integridad de los datos en la fuente y evitar errores de consulta en el tiempo de ejecución.

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

¿Qué sigue?