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

Usa este documento para conocer los beneficios de usar vistas de SQL para crear un gráfico. En este documento, se incluyen los beneficios de crear gráficos con vistas, los requisitos y las consideraciones para ayudarte a decidir si debes usar tablas o vistas para crear un gráfico.

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

Beneficios de crear gráficos 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 gráfico a partir de vistas de SQL, pero no puedes crear una vista que consulte un gráfico.

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

Requisitos para usar vistas y crear gráficos

Debes cumplir con estos requisitos cuando uses vistas para crear elementos del gráfico:

Usa la cláusula KEY cuando especifiques un elemento de gráfico

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

Usa vistas que garanticen que los nodos y los bordes sean únicos

Las vistas que definen tablas de nodos o aristas deben seguir uno de los siguientes patrones para garantizar que los nodos y las aristas sean únicos:

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

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

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 gráfico coincide con las columnas de clave primaria de la tabla base. Por este motivo, cada fila de nodo o borde que produce la vista es única.

Por ejemplo, la siguiente instrucción selecciona un subconjunto de filas de la tabla Account. El gráfico 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 estas cláusulas usan 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)
  );

Consideraciones para usar vistas

Cuando usas vistas para definir elementos del gráfico, lo siguiente puede ayudarte a diseñar e implementar un gráfico eficaz:

Rendimiento de las consultas del gráfico de propiedades

Cuando definas elementos de gráficos en vistas que realizan transformaciones de datos (por ejemplo, operaciones GROUP BY, UNNEST o JOIN), evalúa con cuidado 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 una coincidencia de patrones de elementos.

Optimización del esquema del grafo

Cuando usas vistas para definir elementos del gráfico, algunas optimizaciones del esquema del gráfico pueden ser menos eficaces que cuando usas tablas para definir elementos del gráfico.

Vistas que proyectan la clave primaria de una sola tabla

Si una vista es una proyección de una sola tabla base, las optimizaciones en esa tabla subyacente siguen siendo efectivas para las consultas de grafos. Por ejemplo, aplicar las siguientes técnicas a las tablas base proporciona beneficios de rendimiento similares para los elementos del gráfico 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. Por este motivo, las optimizaciones del 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 gráficos basados en vistas

Las vistas no se materializan, 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. Por lo tanto, para insertar, actualizar o descartar nodos o aristas en un gráfico creado a partir de vistas, debes modificar los datos en las tablas que se usan para crear las vistas.

Manejo de errores de gráficos para aplicar la integridad de los datos

Cuando uses vistas para definir elementos del gráfico, 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 gráfico basado en vistas fallen en el tiempo de ejecución.

Por ejemplo, cuando transicionas de un esquema no definido a un grafo formalizado, usa restricciones CHECK 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?