Información general sobre los esquemas

En esta página se describen los requisitos del esquema de Spanner, cómo usar el esquema para crear relaciones jerárquicas y las funciones del esquema. También introduce tablas intercaladas, que pueden mejorar el rendimiento de las consultas al consultar tablas en una relación superior-secundaria.

Un esquema es un espacio de nombres que contiene objetos de base de datos, como tablas, vistas, índices y funciones. Los esquemas se usan para organizar objetos, aplicar privilegios de control de acceso pormenorizado y evitar conflictos de nombres. Debes definir un esquema para cada base de datos de Spanner.

También puede segmentar y almacenar filas en su tabla de base de datos en diferentes regiones geográficas. Para obtener más información, consulta el artículo Introducción a las particiones geográficas.

Datos con tipado fuerte

Los datos de Spanner tienen un tipado fuerte. Los tipos de datos incluyen tipos escalares y complejos, que se describen en Tipos de datos en GoogleSQL y Tipos de datos de PostgreSQL.

Selecciona una clave principal

Las bases de datos de Spanner pueden contener una o varias tablas. Las tablas se estructuran en filas y columnas. El esquema de la tabla define una o varias columnas de la tabla como la clave principal de la tabla, que identifica de forma única cada fila. Las claves principales siempre se indexan para buscar filas rápidamente. Si quiere actualizar o eliminar filas de una tabla, esta debe tener una clave principal. Una tabla sin columnas de clave principal solo puede tener una fila. Solo las bases de datos con dialecto GoogleSQL pueden tener tablas sin clave principal.

A menudo, tu aplicación ya tiene un campo que se adapta de forma natural para usarlo como clave principal. Por ejemplo, en una tabla Customers, puede haber un CustomerId proporcionado por la aplicación que funcione bien como clave principal. En otros casos, es posible que tengas que generar una clave principal al insertar la fila. Normalmente, se trata de un valor entero único sin importancia empresarial (una clave principal subrogada).

En cualquier caso, debes evitar crear puntos de acceso con la clave principal que elijas. Por ejemplo, si insertas registros con un número entero que aumenta de forma regular como clave, siempre debes insertarlo al final del espacio de clave. Esto no es recomendable porque Spanner divide los datos entre servidores por intervalos de claves, lo que significa que las inserciones se dirigirán a un solo servidor, lo que creará un punto de acceso. Hay técnicas que pueden distribuir la carga entre varios servidores y evitar los puntos de acceso:

Relaciones de tablas superiores y secundarias

Hay dos formas de definir relaciones entre tablas superiores y secundarias en Spanner: intercalado de tablas y claves externas.

El intercalado de tablas de Spanner es una buena opción para muchas relaciones entre tablas superiores y tablas secundarias. Con la intercalación, Spanner coloca físicamente las filas secundarias junto a las filas principales en el almacenamiento. La colocación conjunta puede mejorar el rendimiento de forma significativa. Por ejemplo, si tienes una tabla Customers y una tabla Invoices, y tu aplicación obtiene con frecuencia todas las facturas de un cliente, puedes definir Invoices como una tabla secundaria intercalada de Customers. Al hacerlo, estás declarando una relación de ubicación de datos entre dos tablas independientes. Estás indicando a Spanner que almacene una o varias filas de Invoices con una fila de Customers. Esta relación entre elementos principales y secundarios se aplica cuando se intercala con la cláusula INTERLEAVE IN PARENT. INTERLEAVE IN comparten las mismas características de intercalado de filas físicas, pero Spanner no aplica la integridad referencial entre la tabla superior y la secundaria.

Para asociar una tabla secundaria con una tabla superior, usa DDL que declare la tabla secundaria como intercalada en la tabla superior e incluye la clave principal de la tabla superior como la primera parte de la clave principal compuesta de la tabla secundaria.

Para obtener más información sobre la intercalación, consulta Crear tablas intercaladas.

Las claves externas son una solución más general para tablas superiores y secundarias, y se pueden usar en otros casos prácticos. No están limitadas a columnas de claves principales. Las tablas pueden tener varias relaciones de claves externas, tanto como tabla superior en algunas relaciones como tabla secundaria en otras. Sin embargo, una relación de clave externa no implica que las tablas se encuentren en la misma ubicación en la capa de almacenamiento.

Google recomienda que elija entre representar las relaciones entre tablas superiores y secundarias en forma de tablas intercaladas o claves externas, pero no usar las 2 funciones a la vez. Para obtener más información sobre las claves externas y su comparación con las tablas intercaladas, consulta el resumen de las claves externas.

Claves principales de tablas intercaladas

Para el entrelazado, cada tabla debe tener una clave principal. Si declaras que una tabla es una secundaria intercalada de otra tabla, la tabla debe tener una clave principal compuesta que incluya todos los componentes de la clave principal de la tabla superior, en el mismo orden y, normalmente, una o más columnas adicionales de la tabla secundaria.

Spanner almacena las filas ordenadas por los valores de clave principal, con las filas secundarias insertadas entre las filas principales. Consulta una ilustración de las filas intercaladas en la sección Crear tablas intercaladas de esta página.

En resumen, Spanner puede colocar filas de tablas relacionadas en ubicaciones compartidas. En los ejemplos de esquemas se muestra el aspecto de este diseño físico.

División de bases de datos

Puedes definir jerarquías de relaciones entre elementos superiores y secundarios intercalados de hasta siete niveles de profundidad, lo que significa que puedes colocar filas de siete tablas independientes en el mismo lugar. Si el tamaño de los datos de tus tablas es pequeño, es probable que un solo servidor de Spanner pueda gestionar tu base de datos. Pero ¿qué ocurre cuando tus tablas relacionadas crecen y empiezan a alcanzar los límites de recursos de un servidor individual? Spanner es una base de datos distribuida, lo que significa que, a medida que crece tu base de datos, Spanner divide tus datos en fragmentos denominados "divisiones". Las divisiones individuales pueden moverse de forma independiente entre sí y asignarse a diferentes servidores, que pueden estar en ubicaciones físicas distintas. Un split contiene un intervalo de filas contiguas. Las claves de inicio y fin de este intervalo se denominan "límites de división". Spanner añade y elimina automáticamente límites de divisiones en función del tamaño y la carga, lo que cambia el número de divisiones de la base de datos.

División basada en la carga

Para ver un ejemplo de cómo realiza Spanner la división basada en la carga para mitigar los puntos de acceso de lectura, supongamos que tu base de datos contiene una tabla con 10 filas que se leen con más frecuencia que el resto de las filas de la tabla. Spanner puede añadir límites de división entre cada una de esas 10 filas para que cada una de ellas se gestione en un servidor diferente, en lugar de permitir que todas las lecturas de esas filas consuman los recursos de un solo servidor.

Por lo general, si sigues las prácticas recomendadas para el diseño de esquemas, Spanner puede mitigar los puntos de acceso de forma que el rendimiento de lectura mejore cada pocos minutos hasta que satures los recursos de tu instancia o te encuentres en situaciones en las que no se puedan añadir nuevos límites de división (porque tienes una división que abarca una sola fila sin elementos secundarios intercalados).

Esquemas con nombre

Los esquemas con nombre te ayudan a organizar datos similares. Esto te ayuda a encontrar rápidamente objetos en la consola Google Cloud , aplicar privilegios y evitar colisiones de nombres.

Los esquemas con nombre, al igual que otros objetos de base de datos, se gestionan mediante DDL.

Los esquemas con nombre de Spanner te permiten usar nombres completos (FQNs) para consultar datos. Los FQNs te permiten combinar el nombre del esquema y el nombre del objeto para identificar objetos de la base de datos. Por ejemplo, puede crear un esquema llamado warehouse para la unidad de negocio del almacén. Las tablas que usan este esquema pueden incluir product, order y customer information. También puedes crear un esquema llamado fulfillment para la unidad de negocio de gestión de pedidos. Este esquema también podría tener tablas llamadas product, order y customer information. En el primer ejemplo, el FQN es warehouse.product y, en el segundo, fulfillment.product. De esta forma, se evitan confusiones en situaciones en las que varios objetos tienen el mismo nombre.

En el DDL de CREATE SCHEMA, los objetos de tabla tienen un nombre completo (FQN), por ejemplo, sales.customers, y un nombre abreviado, por ejemplo, sales.

Los siguientes objetos de base de datos admiten esquemas con nombre:

  • TABLE
    • CREATE
    • INTERLEAVE IN [PARENT]
    • FOREIGN KEY
    • SYNONYM
  • VIEW
  • INDEX
  • FOREIGN KEY
  • SEQUENCE

Para obtener más información sobre cómo usar esquemas con nombre, consulta Gestionar esquemas con nombre.

Usar el control de acceso pormenorizado con esquemas con nombre

Los esquemas con nombre te permiten conceder acceso a nivel de esquema a cada objeto del esquema. Esto se aplica a los objetos de esquema que existan en el momento en que concedas acceso. Debe conceder acceso a los objetos que se añadan más adelante.

El control de acceso pormenorizado limita el acceso a grupos completos de objetos de base de datos, como tablas, columnas y filas de la tabla.

Para obtener más información, consulta Conceder privilegios de control de acceso detallado a esquemas con nombre.

Ejemplos de esquemas

En los ejemplos de esquemas de esta sección se muestra cómo crear tablas principales y secundarias con y sin intercalación, y se ilustran los diseños físicos de los datos correspondientes.

Crear una tabla principal

Supongamos que estás creando una aplicación de música y necesitas una tabla que almacene filas de datos de cantantes:

Tabla de cantantes con cinco filas y cuatro columnas

Ten en cuenta que la tabla contiene una columna de clave principal, SingerId, que aparece a la izquierda de la línea en negrita, y que las tablas se organizan por filas y columnas.

Puedes definir la tabla con el siguiente DDL:

GoogleSQL

CREATE TABLE Singers (
SingerId   INT64 NOT NULL PRIMARY KEY,
FirstName  STRING(1024),
LastName   STRING(1024),
SingerInfo BYTES(MAX),
);

PostgreSQL

CREATE TABLE singers (
singer_id   BIGINT PRIMARY KEY,
first_name  VARCHAR(1024),
last_name   VARCHAR(1024),
singer_info BYTEA
);

Ten en cuenta lo siguiente sobre el esquema de ejemplo:

  • Singers es una tabla de la raíz de la jerarquía de la base de datos (porque no se ha definido como secundaria intercalada de otra tabla).
  • En las bases de datos con dialecto GoogleSQL, las columnas de clave principal suelen estar anotadas con NOT NULL (aunque puedes omitir esta anotación si quieres permitir valores NULL en las columnas de clave. Para obtener más información, consulte Columnas clave.
  • Las columnas que no se incluyen en la clave principal se denominan columnas no clave y pueden tener una anotación NOT NULL opcional.
  • Las columnas que usan el tipo STRING o BYTES en GoogleSQL deben definirse con una longitud, que representa el número máximo de caracteres Unicode que se pueden almacenar en el campo. La especificación de longitud es opcional para los tipos varchar y character varying de PostgreSQL. Para obtener más información, consulta Tipos de datos escalares en el caso de las bases de datos con dialecto GoogleSQL y Tipos de datos de PostgreSQL en el caso de las bases de datos con dialecto PostgreSQL.

¿Cómo es la disposición física de las filas de la tabla Singers? En el siguiente diagrama se muestran las filas de la tabla Singers almacenadas por clave principal ("Singers(1)" y, a continuación, "Singers(2)", donde el número entre paréntesis es el valor de la clave principal).

Filas de ejemplo de una tabla almacenada en orden de clave principal

En el diagrama anterior se muestra un ejemplo de límite de división entre las filas con las claves Singers(3) y Singers(4), con los datos de las divisiones resultantes asignados a diferentes servidores. A medida que crece esta tabla, es posible que las filas de datos de Singers se almacenen en ubicaciones diferentes.

Crear tablas principales y secundarias

Supongamos que ahora quieres añadir algunos datos básicos sobre los álbumes de cada cantante a la aplicación de música.

Tabla de álbumes con cinco filas y tres columnas

Ten en cuenta que la clave principal de Albums se compone de dos columnas: SingerId y AlbumId, para asociar cada álbum con su cantante. El siguiente esquema de ejemplo define las tablas Albums y Singers en la raíz de la jerarquía de la base de datos, lo que las convierte en tablas hermanas.

-- Schema hierarchy:
-- + Singers (sibling table of Albums)
-- + Albums (sibling table of Singers)

GoogleSQL

CREATE TABLE Singers (
 SingerId   INT64 NOT NULL PRIMARY KEY,
 FirstName  STRING(1024),
 LastName   STRING(1024),
 SingerInfo BYTES(MAX),
);

CREATE TABLE Albums (
SingerId     INT64 NOT NULL,
AlbumId      INT64 NOT NULL,
AlbumTitle   STRING(MAX),
) PRIMARY KEY (SingerId, AlbumId);

PostgreSQL

CREATE TABLE singers (
singer_id   BIGINT PRIMARY KEY,
first_name  VARCHAR(1024),
last_name   VARCHAR(1024),
singer_info BYTEA
);

CREATE TABLE albums (
singer_id     BIGINT,
album_id      BIGINT,
album_title   VARCHAR,
PRIMARY KEY (singer_id, album_id)
);

El diseño físico de las filas de Singers y Albums es similar al del siguiente diagrama, con filas de la tabla Albums almacenadas por clave principal contigua y, a continuación, filas de Singers almacenadas por clave principal contigua:

Diseño físico de las filas

Una nota importante sobre el esquema es que Spanner no asume ninguna relación de localidad de datos entre las tablas Singers y Albums, ya que son tablas de nivel superior. A medida que la base de datos crece, Spanner puede añadir límites de división entre cualquiera de las filas. Esto significa que las filas de la tabla Albums podrían acabar en una división diferente de las filas de la tabla Singers, y las dos divisiones podrían moverse de forma independiente.

En función de las necesidades de tu aplicación, puede que no haya problema en que los datos de Albums se encuentren en divisiones diferentes a los datos de Singers. Sin embargo, esto puede conllevar una penalización del rendimiento debido a la necesidad de coordinar las lecturas y las actualizaciones en distintos recursos. Si tu aplicación necesita recuperar información con frecuencia sobre todos los álbumes de un cantante concreto, debes crear Albums como tabla secundaria intercalada de Singers, que coloca las filas de las dos tablas en el mismo lugar a lo largo de la dimensión de la clave principal. En el siguiente ejemplo se explica con más detalle.

Crear tablas intercaladas

Una tabla intercalada es una tabla que declaras como secundaria intercalada de otra tabla porque quieres que las filas de la tabla secundaria se almacenen físicamente con la fila superior asociada. Como hemos mencionado antes, la clave principal de la tabla superior debe ser la primera parte de la clave principal compuesta de la tabla secundaria.

Una vez que has intercalado una tabla, el cambio es permanente. No puedes deshacer la intercalación. En su lugar, debes volver a crear la tabla y migrar los datos a ella.

Mientras diseñas tu aplicación de música, te das cuenta de que la aplicación necesita acceder con frecuencia a las filas de la tabla Albums cuando accede a una fila Singers. Por ejemplo, si accedes a la fila Singers(1), también debes acceder a las filas Albums(1, 1) y Albums(1, 2). En este caso, Singers y Albums deben tener una relación de localidad de datos sólida. Puedes declarar esta relación de ubicación de datos creando Albums como tabla secundaria intercalada de Singers.

-- Schema hierarchy:
-- + Singers
--   + Albums (interleaved table, child table of Singers)

La línea en negrita del siguiente esquema muestra cómo crear Albums como una tabla intercalada de Singers.

GoogleSQL

CREATE TABLE Singers (
 SingerId   INT64 NOT NULL PRIMARY KEY,
 FirstName  STRING(1024),
 LastName   STRING(1024),
 SingerInfo BYTES(MAX),
 );

CREATE TABLE Albums (
 SingerId     INT64 NOT NULL,
 AlbumId      INT64 NOT NULL,
 AlbumTitle   STRING(MAX),
 ) PRIMARY KEY (SingerId, AlbumId),
INTERLEAVE IN PARENT Singers ON DELETE CASCADE;

PostgreSQL

CREATE TABLE singers (
 singer_id   BIGINT PRIMARY KEY,
 first_name  VARCHAR(1024),
 last_name   VARCHAR(1024),
 singer_info BYTEA
 );

CREATE TABLE albums (
 singer_id     BIGINT,
 album_id      BIGINT,
 album_title   VARCHAR,
 PRIMARY KEY (singer_id, album_id)
 )
 INTERLEAVE IN PARENT singers ON DELETE CASCADE;

Observaciones sobre este esquema:

  • SingerId, que es la primera parte de la clave principal de la tabla secundaria Albums, también es la clave principal de su tabla superior Singers.
  • La anotación ON DELETE CASCADE indica que, cuando se elimina una fila de la tabla principal, sus filas secundarias también se eliminan automáticamente. Si una tabla secundaria no tiene esta anotación o la anotación es ON DELETE NO ACTION, debes eliminar las filas secundarias antes de poder eliminar la fila superior.
  • Las filas intercaladas se ordenan primero por las filas de la tabla superior y, a continuación, por las filas contiguas de la tabla secundaria que comparten la clave principal de la tabla superior. Por ejemplo, "Cantantes(1)", luego "Álbumes(1, 1)" y, después, "Álbumes(1, 2)".
  • La relación de localidad de los datos de cada cantante y de su álbum se conserva si se divide esta base de datos, siempre que el tamaño de una fila Singers y de todas sus filas Albums no supere el límite de tamaño de la división y no haya ningún punto de acceso en ninguna de estas filas Albums.
  • La fila superior debe existir para poder insertar filas secundarias. La fila principal ya puede estar en la base de datos o se puede insertar antes de insertar las filas secundarias en la misma transacción.

Las filas de álbumes se intercalan entre las filas de cantantes

Supongamos que quiere modelar Projects y su Resources como tablas intercaladas. En algunos casos, puede ser útil INTERLEAVE IN, que permite que no sea necesario que exista la fila Projects para que existan las entidades que contiene (por ejemplo, si se ha eliminado un proyecto, pero sus recursos deben limpiarse antes de eliminarlo).

GoogleSQL

CREATE TABLE Projects (
  ProjectId   INT64 NOT NULL,
  ProjectName STRING(1024),
) PRIMARY KEY (ProjectId);

CREATE TABLE Resources (
  ProjectId    INT64 NOT NULL,
  ResourceId   INT64 NOT NULL,
  ResourceName STRING(1024),
) PRIMARY KEY (ProjectId, ResourceId),
  INTERLEAVE IN Projects;

PostgreSQL

CREATE TABLE Projects (
  ProjectId   BIGINT PRIMARY KEY,
  ProjectName VARCHAR(1024),
);

CREATE TABLE Resources (
  ProjectId    BIGINT,
  ResourceId   BIGINT,
  ResourceName VARCHAR(1024),
  PRIMARY KEY (ProjectId, ResourceId)
) INTERLEAVE IN Projects;

Ten en cuenta que, en este ejemplo, usamos la cláusula INTERLEAVE IN Projects en lugar de INTERLEAVE IN PARENT Projects. Esto indica que no aplicamos la relación entre proyectos y recursos.

En este ejemplo, las filas Resources(1, 10) y Resources(1, 20) pueden existir en la base de datos aunque no exista la fila Projects(1). Projects(1) se puede eliminar aunque Resources(1, 10) y Resources(1, 20) sigan existiendo, y la eliminación no afecta a estas filas Resources.

Crear una jerarquía de tablas intercaladas

La relación entre la tabla superior Singers y la tabla secundaria Albums se puede ampliar a más tablas descendientes. Por ejemplo, puedes crear una tabla intercalada llamada Songs como elemento secundario de Albums para almacenar la lista de canciones de cada álbum:

Tabla de canciones con seis filas y cuatro columnas

Songs debe tener una clave principal que incluya todas las claves principales de las tablas que estén en un nivel superior de la jerarquía, es decir, SingerId y AlbumId.

-- Schema hierarchy:
-- + Singers
--   + Albums (interleaved table, child table of Singers)
--     + Songs (interleaved table, child table of Albums)

GoogleSQL

CREATE TABLE Singers (
 SingerId   INT64 NOT NULL PRIMARY KEY,
 FirstName  STRING(1024),
 LastName   STRING(1024),
 SingerInfo BYTES(MAX),
);

CREATE TABLE Albums (
 SingerId     INT64 NOT NULL,
 AlbumId      INT64 NOT NULL,
 AlbumTitle   STRING(MAX),
) PRIMARY KEY (SingerId, AlbumId),
 INTERLEAVE IN PARENT Singers ON DELETE CASCADE;

CREATE TABLE Songs (
 SingerId     INT64 NOT NULL,
 AlbumId      INT64 NOT NULL,
 TrackId      INT64 NOT NULL,
 SongName     STRING(MAX),
) PRIMARY KEY (SingerId, AlbumId, TrackId),
 INTERLEAVE IN PARENT Albums ON DELETE CASCADE;

PostgreSQL

CREATE TABLE singers (
 singer_id   BIGINT PRIMARY KEY,
 first_name  VARCHAR(1024),
 last_name   VARCHAR(1024),
 singer_info BYTEA
 );

CREATE TABLE albums (
 singer_id     BIGINT,
 album_id      BIGINT,
 album_title   VARCHAR,
 PRIMARY KEY (singer_id, album_id)
 )
 INTERLEAVE IN PARENT singers ON DELETE CASCADE;

CREATE TABLE songs (
 singer_id     BIGINT,
 album_id      BIGINT,
 track_id      BIGINT,
 song_name     VARCHAR,
 PRIMARY KEY (singer_id, album_id, track_id)
 )
 INTERLEAVE IN PARENT albums ON DELETE CASCADE;

En el siguiente diagrama se muestra una vista física de las filas intercaladas.

Las canciones se intercalan en los álbumes, que a su vez se intercalan entre los cantantes.

En este ejemplo, a medida que aumenta el número de cantantes, Spanner añade límites de división entre ellos para conservar la localidad de los datos entre un cantante y los datos de su álbum y sus canciones. Sin embargo, si el tamaño de una fila de cantante y sus filas secundarias supera el límite de tamaño de división o se detecta un punto de acceso en las filas secundarias, Spanner intenta añadir límites de división para aislar esa fila de punto de acceso junto con todas las filas secundarias que haya debajo.

En resumen, una tabla superior junto con todas sus tablas secundarias y descendientes forman una jerarquía de tablas en el esquema. Aunque cada tabla de la jerarquía es lógicamente independiente, entrelazarlas físicamente de esta forma puede mejorar el rendimiento, ya que se combinan las tablas previamente y se puede acceder a las filas relacionadas juntas, al tiempo que se minimizan los accesos al almacenamiento.

Combinaciones con tablas intercaladas

Si es posible, combine los datos de las tablas intercaladas por clave principal. Como cada fila intercalada se suele almacenar físicamente en la misma división que su fila principal, Spanner puede realizar combinaciones por clave principal de forma local, lo que minimiza el acceso al almacenamiento y el tráfico de red. En el ejemplo siguiente, Singers y Albums se combinan en la clave principal SingerId.

GoogleSQL

SELECT s.FirstName, a.AlbumTitle
FROM Singers AS s JOIN Albums AS a ON s.SingerId = a.SingerId;

PostgreSQL

SELECT s.first_name, a.album_title
FROM singers AS s JOIN albums AS a ON s.singer_id = a.singer_id;

Grupos de localidades

Spanner usa grupos de localidad para conservar las relaciones de localidad de los datos en las columnas de las tablas. Si no creas ningún grupo de localidad para tus tablas, Spanner agrupa todas las columnas en el grupo de localidad default y almacena los datos de todas las tablas en almacenamiento SSD. Puedes usar grupos de localidades para hacer lo siguiente:

  • Usa el almacenamiento por niveles. El almacenamiento por niveles es una función de almacenamiento totalmente gestionada que te permite elegir si quieres almacenar tus datos en unidades de estado sólido (SSD) o en unidades de disco duro (HDD). De forma predeterminada, sin usar el almacenamiento por niveles, Spanner almacena todos los datos en almacenamiento SSD.

  • Use la agrupación de columnas para almacenar las columnas especificadas por separado de otras columnas. Como los datos de las columnas especificadas se almacenan por separado, leer datos de esas columnas es más rápido que si todos los datos estuvieran agrupados. Para usar la agrupación por columnas, debes crear un grupo de localidades sin especificar ninguna opción de almacenamiento por niveles. Spanner usa grupos de localidad para almacenar las columnas especificadas por separado. Si se especifica, las columnas heredan su política de almacenamiento por niveles de la tabla o del grupo de localidad predeterminado. A continuación, usa la CREATE TABLE declaración de DDL para definir un grupo de localidad para las columnas especificadas o usa la ALTER TABLE declaración de DDL para modificar el grupo de localidad que usa la columna de una tabla. La instrucción DDL determina las columnas que se almacenan en el grupo de localidad. Por último, puede leer los datos de estas columnas de forma más eficiente.

Columnas clave

En esta sección se incluyen algunas notas sobre las columnas clave.

Cambiar las claves de una tabla

Las claves de una tabla no se pueden cambiar; no puedes añadir una columna de clave a una tabla ni eliminarla.

Almacenar valores NULL en una clave principal

En GoogleSQL, si quieres almacenar NULL en una columna de clave principal, omite la cláusula NOT NULL de esa columna en el esquema. (Las bases de datos con dialecto PostgreSQL no admiten valores NULL en una columna de clave principal).

A continuación, se muestra un ejemplo de omisión de la cláusula NOT NULL en la columna de clave principal. SingerId Ten en cuenta que, como SingerId es la clave principal, solo puede haber una fila que almacene NULL en esa columna.

CREATE TABLE Singers (
  SingerId   INT64 PRIMARY KEY,
  FirstName  STRING(1024),
  LastName   STRING(1024),
);

La propiedad que se puede añadir como nula de la columna de clave principal debe coincidir entre las declaraciones superior y secundaria. En este ejemplo, no se permite NOT NULL en la columna Albums.SingerId porque Singers.SingerId lo omite.

CREATE TABLE Singers (
  SingerId   INT64 PRIMARY KEY,
  FirstName  STRING(1024),
  LastName   STRING(1024),
);

CREATE TABLE Albums (
  SingerId     INT64 NOT NULL,
  AlbumId      INT64 NOT NULL,
  AlbumTitle   STRING(MAX),
) PRIMARY KEY (SingerId, AlbumId),
  INTERLEAVE IN PARENT Singers ON DELETE CASCADE;

Tipos no permitidos

Las siguientes columnas no pueden ser de tipo ARRAY:

  • Las columnas de clave de una tabla.
  • Las columnas de clave de un índice.

Diseño para arquitectura multicliente

Puede que quieras implementar la arquitectura multiempresa si almacenas datos que pertenecen a diferentes clientes. Por ejemplo, un servicio de música puede querer almacenar el contenido de cada discográfica por separado.

Propiedad múltiple clásica

La forma clásica de diseñar para multitenancy es crear una base de datos independiente para cada cliente. En este ejemplo, cada base de datos tiene su propia tabla Singers:

Base de datos 1: Ackworth Records
SingerId FirstName (Nombre) LastName
1MarcRichards
2CatalinaSmith
Base de datos 2: Cama Records
SingerId FirstName (Nombre) LastName
1AliceTrentor
2GabrielWright
Base de datos 3: Eagan Records
SingerId FirstName (Nombre) LastName
1BenjamínMartinez
2HannahHarris

Propiedad múltiple gestionada por esquemas

Otra forma de diseñar la multitenencia en Spanner es tener todos los clientes en una sola tabla de una sola base de datos y usar un valor de clave principal diferente para cada cliente. Por ejemplo, puede incluir una columna de CustomerId clave en sus tablas. Si CustomerId es la primera columna clave, los datos de cada cliente tendrán una buena localidad. Spanner puede usar de forma eficaz las divisiones de la base de datos para maximizar el rendimiento en función del tamaño de los datos y los patrones de carga. En el siguiente ejemplo, hay una sola tabla Singers para todos los clientes:

Base de datos multiinquilino de Spanner
CustomerId SingerId FirstName (Nombre) LastName
11MarcRichards
12CatalinaSmith
21AliceTrentor
22GabrielWright
31BenjamínMartinez
32HannahHarris

Si debes tener bases de datos independientes para cada arrendatario, debes tener en cuenta las siguientes restricciones:

  • Hay límites en el número de bases de datos por instancia y en el número de tablas e índices por base de datos. En función del número de clientes, puede que no sea posible tener bases de datos o tablas independientes.
  • Añadir tablas e índices no intercalados puede llevar mucho tiempo. Es posible que no consigas el rendimiento que quieres si el diseño de tu esquema depende de la adición de nuevas tablas e índices.

Si quieres crear bases de datos independientes, es posible que tengas más éxito si distribuyes tus tablas entre las bases de datos de forma que cada base de datos tenga un número reducido de cambios de esquema por semana.

Si creas tablas e índices independientes para cada cliente de tu aplicación, no pongas todas las tablas e índices en la misma base de datos. En su lugar, divídelas en varias bases de datos para mitigar los problemas de rendimiento que se producen al crear un gran número de índices.

Para obtener más información sobre otros patrones de gestión de datos y diseño de aplicaciones para el multitenancy, consulta Implementar multitenancy en Spanner.