Esquema y modelo de datos

Resumen del modelo de datos

Una base de datos de Cloud Spanner puede contener entre una y varias tablas. Estas tablas se parecen a las tablas de bases de datos relacionales porque están distribuidas en filas, columnas y valores, y contienen claves principales. Los datos en Cloud Spanner tienen un alto nivel de especificación: se debe definir un esquema para cada base de datos, y en dicho esquema se deben definir los tipos de datos de todas las columnas de cada tabla. Entre los tipos de datos permitidos se incluyen tipos escalares y de matriz, que se explican con más detalle en el apartado sobre tipos de datos. También puedes definir uno o más índices secundarios en una tabla, como se describe en el apartado de índices secundarios.

Relaciones de tablas superiores y secundarias

Se pueden definir varias tablas en una base de datos y, de forma opcional, se pueden definir relaciones superiores y secundarias entre las tablas si deseas que Cloud Spanner ubique físicamente las filas para poder realizar una recuperación eficaz. Por ejemplo, si tienes una tabla Customers y otra Invoices, y la aplicación obtiene con frecuencia todas las facturas de un cliente determinado, puedes definir Invoices como una tabla secundaria de Customers. Al hacerlo, estás declarando una relación de localidad de datos entre dos tablas lógicamente independientes, es decir, le estás diciendo a Cloud Spanner que almacene físicamente una o más filas de Invoices con una fila de Customers.

Claves principales

¿Cómo se le indica a Cloud Spanner qué filas de Invoices debe almacenar con qué filas de Customers? Se hace mediante la clave principal de estas tablas. Cada tabla debe tener una clave principal, y dicha clave puede estar compuesta por cero o más columnas de esa tabla. Si declaras que una tabla es una secundaria de otra tabla, todas las columnas de clave primaria de la tabla superior deben constituir el prefijo de la clave principal de la tabla secundaria. Esto significa que si la clave principal de una tabla superior está compuesta de N columnas, la clave principal de cada una de las tablas secundarias también debe estar compuesta por esas mismas N columnas, en el mismo orden y comenzando por la misma.

Cloud Spanner almacena las filas ordenadas por valores de clave principal, con filas secundarias insertadas entre las filas superiores que comparten el mismo prefijo de clave principal. Esta inserción de filas secundarias entre filas superiores a lo largo de la dimensión de clave primaria se denomina "intercalado", y las tablas secundarias también se conocen como "tablas intercaladas" (echa un vistazo a una imagen de filas intercaladas en la vista física del ejemplo de esquema 3 que se muestra a continuación).

En resumen, las claves principales en Cloud Spanner te permiten ubicar físicamente filas de tablas relacionadas. Mediante los ejemplos de esquema que aparecen a continuación, se muestra cómo se ve esta disposición física.

Elegir una clave principal

Si la clave principal está compuesta de una o más columnas, necesitarás una clave primaria única para cada fila. A menudo, la aplicación ya tiene un campo apto para usarlo como clave principal. Por ejemplo, en la tabla Customers que vimos anteriormente, puede haber un CustomerId proporcionado por la aplicación que sirva como la clave principal. En otros casos, puede que debas generar una clave principal al insertar la fila, como un valor INT64 único generado mediante una biblioteca UUID.

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. Esta opción es poco recomendable, ya que Cloud Spanner divide los datos entre los servidores en función de intervalos de claves, lo que significa que las inserciones se dirigirán a un solo servidor, lo que crea un punto de acceso. Una técnica habitual para distribuir la carga entre varios servidores es usar la clave única real y usar el hash (o el hash junto con la clave única) como clave principal. Esta acción ayuda a garantizar que los registros insertados se distribuyen por el espacio clave para evitar crear puntos de acceso. Obtén más información sobre esta técnica en el apartado sobre prácticas recomendadas.

División de bases de datos

Puedes definir jerarquías de relaciones superiores y secundarias entre tablas de hasta siete capas de profundidad, lo que significa que puedes ubicar filas de siete tablas lógicamente independientes. Si los datos de las tablas no son de gran tamaño, puede que la base de datos esté gestionada por un único servidor de Cloud Spanner. Pero ¿qué sucede cuando aumentan las tablas relacionadas y comienzan a alcanzar los límites de recursos de un servidor individual? Cloud Spanner es una base de datos distribuida, lo que significa que, a medida que la base de datos aumenta, Cloud Spanner divide los datos en fragmentos llamados "divisiones" en los que las divisiones individuales se pueden mover de forma independiente y asignarse a diferentes servidores, que pueden encontrarse en ubicaciones físicas distintas. Una división es un conjunto de filas en una tabla de nivel superior (en otras palabras, no intercalada), en la cual las filas se ordenan por clave principal. Las claves de inicio y fin de este intervalo se llaman "límites divididos". Cloud Spanner añade y elimina automáticamente los límites divididos, lo que cambia el número de divisiones en la base de datos.

Cloud Spanner divide los datos en función de la carga: añade límites divididos automáticamente cuando detecta una gran cantidad de cargas de lectura o escritura entre muchas claves de una división. Tienes algo de control sobre cómo se dividen los datos, ya que Cloud Spanner solo puede trazar límites divididos entre filas de tablas que se encuentren en la raíz de una jerarquía (es decir, tablas que no estén intercaladas en una tabla superior). Además, las filas de una tabla intercalada no se pueden separar de la fila correspondiente de la tabla superior debido a que las filas de la tabla intercalada se almacenan en orden de clave principal junto con la fila de la tabla superior que comparte el mismo prefijo de clave principal (echa un vistazo a la ilustración de este casi en la vista física del ejemplo de esquema 4, que se muestra a continuación). Por lo tanto, las relaciones de tablas superiores y secundarias que definas, junto con los valores de clave primaria que establezcas para las filas de las tablas relacionadas, te permiten controlar cómo se fragmentan los datos de forma interna.

División basada en la carga

Como ejemplo de cómo Cloud Spanner realiza la división basada en la carga para mitigar los puntos de acceso de lectura, supón que tu base de datos contiene una tabla con diez filas que se leen con más frecuencia que todas las demás filas de la tabla. Siempre que esa tabla se encuentre en la raíz de la jerarquía de la base de datos (en otras palabras, siempre que no se trate de una tabla intercalada), Cloud Spanner puede añadir límites divididos entre cada una de esas diez filas para que un servidor diferente gestione cada una de ellas, en lugar de permitir que todas las lecturas de esas filas consuman los recursos de un único servidor.

Como regla general, si sigues las prácticas recomendadas para el diseño de esquemas, Cloud Spanner puede mitigar puntos de acceso de lecturas que se dirigen a filas de una tabla no intercalada, de modo que el rendimiento de lectura mejore cada pocos minutos hasta que se saturen los recursos en la instancia o te encuentres con casos en los que no se pueden añadir nuevos límites de división (porque dispones de una división que abarca solo una fila y sus secundarias intercaladas).

Límites de tamaño dividido

Como regla general, el tamaño de cada conjunto de filas relacionadas en una jerarquía de tablas superiores y secundarias debe ser inferior a una pequeña cantidad de GiB. Un conjunto de filas relacionadas en una jerarquía de tablas superiores y secundarias se define de esta forma: (una sola fila de una tabla en la raíz de una jerarquía de base de datos) + (todas las filas de las tablas descendientes de esa tabla que comparten la clave primaria de la fila) + (todas las filas de índices intercalados que comparten la clave principal de la fila).

Ejemplos de esquemas

En los siguientes ejemplos de esquemas se muestra cómo crear tablas de Cloud Spanner, tanto con relaciones superiores y secundarias como sin ellas, y se ilustran los diseños físicos correspondientes de los datos.

Crear una tabla

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

Tabla Singers con 5 filas y 4 columnas.

Vista lógica de filas en una tabla sencilla de cantantes. La columna de la clave principal se sitúa a la izquierda de la línea en negrita.

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 están organizadas por filas, columnas y valores.

Puedes definir la tabla con un esquema de Cloud Spanner como este:

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

El ejemplo de esquema 1 define la tabla de los cantantes

Ten en cuenta lo siguiente sobre el esquema de ejemplo:

  • Singers es una tabla que se encuentra en la raíz de la jerarquía de la base de datos (porque no está definida como secundaria de otra tabla).
  • A las columnas de clave principal se les suele aplicar la anotación NOT NULL (aunque puedes omitirla si quieres permitir que se establezcan valores NULL en las columnas clave; obtén más información en el apartado sobre información de las columnas clave).
  • Las columnas que no están incluidas en la clave principal se denominan columnas sin clave y pueden tener una anotación NOT NULL opcional.
  • Las columnas que usan el tipo STRING o BYTES se deben definir con una longitud, que representa la cantidad máxima de caracteres Unicode que se pueden almacenar en el campo (más detalles en el apartado sobre tipos de datos escalares).

¿Qué aspecto tiene el diseño físico de las filas de la tabla Singers? En el siguiente diagrama se muestran las filas de la tabla Singers almacenadas de forma contigua según la clave principal, también conocido criterio de orden (es decir, "Singers(1)", seguida de "Singers(2)", y así sucesivamente; aquí "Singers(1)" representa la fila en la tabla Singers con la clave principal 1).

Filas de ejemplo de una tabla almacenadas en un orden contiguo según la clave.

Diseño físico de filas de la tabla Singers, con un ejemplo de límite dividido que da como resultado divisiones gestionadas por diferentes servidores.

El diagrama también ilustra los posibles límites de división, que pueden producirse entre cualquier fila de Singers, ya que Singers se encuentra en la raíz de la jerarquía de la base de datos. También ilustra un ejemplo de límite de división entre las filas que obtienen la clave de Singers(3) y Singers(4), con los datos de las divisiones resultantes asignados a diferentes servidores. Esto significa que, a medida que aumente esta tabla, puede que las filas de datos de Singers se almacenen en diferentes ubicaciones.

Crear varias tablas

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

Tabla Albums con 5 filas y 3 columnas

Vista lógica de filas en una tabla Albums. Las columnas de las claves principales se sitúan a la izquierda de la línea en negrita.

Ten en cuenta que la clave principal de Albums está compuesta por 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 del mismo nivel:

-- Schema hierarchy:
-- + Singers (sibling table of Albums)
-- + Albums (sibling table of Singers)
CREATE TABLE Singers (
  SingerId   INT64 NOT NULL,
  FirstName  STRING(1024),
  LastName   STRING(1024),
  SingerInfo BYTES(MAX),
) PRIMARY KEY (SingerId);

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

El ejemplo de esquema 2 define las tablas Singers y Albums, ambas establecidas en la raíz de la jerarquía de la base de datos.

El diseño físico de las filas de Singers y Albums tiene este aspecto, con las filas de la tabla Albums almacenadas de forma contigua según la clave principal primero y las filas de Singers almacenadas de la misma forma después:

Diseño físico de las filas: las filas de Albums y Singers se almacenan cada una en función del valor de la clave

Diseño físico de las filas de las tablas Singers y Albums, ambas establecidas en la raíz de la jerarquía de la base de datos.

Un detalle importante sobre el esquema anterior es que Cloud Spanner no asume ninguna relación de localidad de datos entre las tablas Singers y Albums, ya que son tablas del mismo nivel, es decir, que se encuentran en el mismo nivel de jerarquía en la base de datos. A medida que la base de datos aumenta, Cloud Spanner puede añadir límites divididos entre cualquiera de las filas que se muestran arriba. Esto significa que las filas de la tabla Albums podrían ir a parar a una división diferente que las filas de la tabla Singers, y las dos divisiones podrían moverse independientemente una de otra.

Según las necesidades de la aplicación, podría ser interesante permitir que los datos de Albums se ubiquen en divisiones diferentes a las de los datos de Singers. Sin embargo, si su aplicación necesita recuperar información sobre todos los álbumes de un cantante determinado con frecuencia, debes crear la tabla Albums como secundaria de Singers, que ubica las filas de las dos tablas en la dimensión de la clave principal. En el siguiente ejemplo se explica esto con más detalle.

Crear tablas intercaladas

Supón que, mientras diseñas la aplicación de música, te das cuenta de que esta va a necesitar acceder con frecuencia a las filas de las tablas Singers y Albums para obtener una clave principal determinada (por ejemplo, cada vez que accedes a la fila Singers(1), también debes acceder al filas Albums(1, 1) y Albums(1, 2)). En otras palabras, Singers y Albums deben disponer de una relación de localidad de datos sólida.

Puedes declarar esta relación de localidad de datos al crear la tabla Albums como secundaria o "intercalada" de Singers. Como se mencionó anteriormente, una tabla intercalada es una tabla que se declara como secundaria de otra tabla para que las filas de la tabla secundaria se almacenen físicamente junto a las filas principales asociadas. Como se mencionó anteriormente, el prefijo de la clave principal de una tabla secundaria debe ser la clave principal de la tabla superior.

La línea en negrita que aparece en este esquema muestra cómo crear la tabla Albums como una tabla intercalada de Singers.

-- Schema hierarchy:
-- + Singers
--   + Albums (interleaved table, child table of Singers)
CREATE TABLE Singers (
  SingerId   INT64 NOT NULL,
  FirstName  STRING(1024),
  LastName   STRING(1024),
  SingerInfo BYTES(MAX),
) PRIMARY KEY (SingerId);

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;

El ejemplo de esquema 3 define Albums como tabla secundaria de Singers, con Singers en la raíz de la jerarquía de la base de datos.

Observaciones sobre este esquema:

  • SingerId, que es el prefijo de la clave principal de la tabla secundaria Albums, también es la clave principal de la tabla superior Singers. Esto no resulta necesario si Singers y Albums se encuentran en el mismo nivel de la jerarquía, pero sí se requiere en este esquema porque Albums se declara como una tabla secundaria de Singers.
  • La anotación ON DELETE CASCADE sirve para que, cuando se borre una fila de la tabla superior, las filas secundarias de esta tabla también se eliminen automáticamente (es decir, todas las filas que comiencen por la misma clave principal). Si una tabla secundaria no cuenta con esta propiedad, debes eliminar las filas secundarias antes de poder eliminar la fila superior.
  • Las filas intercaladas se ordenan primero según las filas de la tabla superior y, después, de forma contigua según las filas de la tabla secundaria que toman la clave principal de la superior, es decir, "Singers(1)" seguida de "Albums(1, 1)", "Albums(1, 2)" y así sucesivamente.
  • La relación de localidad de datos de cada cantante y sus datos de álbum se conservaría si esta base de datos se divide, ya que las divisiones solo se pueden insertar entre las filas de la tabla Singers.

Diseño físico de las filas: las filas de Albums se intercalan entre las filas de Singers

Diseño físico de filas de la tabla superior Singers y su tabla secundaria Albums.

Crear una jerarquía de tablas intercaladas

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

Tabla Songs con 6 filas y 4 columnas

Vista lógica de filas en una tabla Songs. Las columnas de las claves principales se sitúan a la izquierda de la línea en negrita.

Songs debe tener una clave principal compuesta por todas las claves principales de las tablas que se encuentran por encima de ella en 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)
CREATE TABLE Singers (
  SingerId   INT64 NOT NULL,
  FirstName  STRING(1024),
  LastName   STRING(1024),
  SingerInfo BYTES(MAX),
) PRIMARY KEY (SingerId);

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;

El ejemplo de esquema 4 define la tabla Songs como secundaria de la tabla Albums, que, a su vez, es secundaria de Singers. Singers se encuentra en la raíz de la jerarquía de la base de datos.

La vista física de filas intercaladas muestra que la relación de localidad de datos se conserva entre un cantante, sus álbumes y los datos de las canciones:

Vistas físicas de filas: las filas de Songs se intercalan en Albums, que a su vez se intercalan en Singers

Diseño físico de las filas de las tablas Singers, Albums y Songs, que forman una jerarquía de tablas intercaladas.

En resumen, una tabla superior junto con todas sus tablas secundarias y descendientes forman una jerarquía de tablas en el esquema. Si bien cada tabla de la jerarquía es lógicamente independiente, al intercalarlas físicamente de esta manera se puede mejorar el rendimiento, ya que se unen previamente las tablas y esto permite acceder a las filas relacionadas a la vez que se minimizan los accesos al disco.

Las tablas intercaladas no son obligatorias en Cloud Spanner, pero se recomienda usarlas en el caso de tablas con relaciones de localidad de datos sólidas. Evita intercalar tablas si existe la posibilidad de que el tamaño de una sola fila y sus descendientes sea mayor que una cantidad pequeña de GiB.

Notas sobre columnas de clave

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

Almacenamiento de valores NULL

Las columnas de clave principal se pueden definir para almacenar valores NULL. Si quieres almacenar valores NULL en una columna de clave principal, omite la cláusula NOT NULL para esa columna en el esquema.

Aquí hay un ejemplo de omisión de la cláusula NOT NULL en la columna de clave principal SingerId. Ten en cuenta que debido a que SingerId es la clave principal, solo puede haber como máximo una fila en la tabla Singers que almacene valores NULL en esa columna.

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

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, Albums.SingerId INT64 NOT NULL no está permitido. La declaración de clave debe omitir la cláusula NOT NULL porque Singers.SingerId la omite.

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

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

Estas columnas no pueden ser de tipo ARRAY:

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

Actualizar esquemas

Cloud Spanner te permite hacer cambios de esquema online sin que se produzcan periodos inactivos. Si quieres actualizar el esquema de una base de datos, usa projects.instances.databases.updateDdl (API REST) o UpdateDatabaseDdl (API RPC) para emitir un lote de una o más declaraciones CREATE, ALTER o DROP que estén descritas en el lenguaje de definición de datos.

Cloud Spanner aplica declaraciones del mismo lote en orden y se detiene al encontrar el primer error. Si la aplicación de una declaración da como resultado un error, esa declaración se restaura, pero los resultados de cualquier declaración aplicada previamente a un lote se conservan.

Cloud Spanner puede intercalar sentencias de diferentes lotes al mezclar potencialmente sentencias de diferentes lotes en el mismo cambio atómico que se aplica a la base de datos. En cada cambio atómico, las declaraciones de diferentes lotes ocurren en un orden arbitrario. Por ejemplo, si un lote contiene la declaración ALTER TABLE MyTable ALTER COLUMN MyColumn STRING(50) y otro contiene ALTER TABLE MyTable ALTER COLUMN MyColumn STRING(20), Cloud Spanner aplicará uno de esos dos estados a la columna, pero no se especifica cuál.

Actualizar esquemas compatibles

Cloud Spanner permite que se apliquen las siguientes actualizaciones al esquema de una base de datos:

  • Añadir nuevas tablas (las columnas en dichas tablas pueden tener el valor NOT NULL).
  • Eliminar una tabla por completo, siempre que no contenga otras tablas o índices intercalados.
  • Añadir una columna de clave no principal a cualquier tabla (dichas columnas no pueden tener el valor NOT NULL).
  • Eliminar una columna de clave no principal de cualquier tabla, a menos que la use un índice secundario.
  • Añadir o eliminar cualquier índice secundario.
  • Cambiar un tipo STRING a un tipo BYTES o un tipo BYTES a un tipo STRING.
  • Aumentar o disminuir el límite de longitud para un tipo STRING o BYTES (incluso a MAX) a menos que sea una columna de clave principal heredada por una o más tablas secundarias.
  • Añadir o eliminar la anotación NOT NULL desde una columna que no sea de clave principal.

Rendimiento del cambio de esquema

Como se mencionó anteriormente, los cambios de esquema en Cloud Spanner no requieren que se produzcan periodos inactivos. Esto implica que, cuando emites un lote de instrucciones de actualización en DDL a una base de datos de Cloud Spanner, puedes continuar escribiendo y leyendo desde la base de datos sin interrupción, mientras que Cloud Spanner aplica los cambios como una operación de larga duración.

La cantidad de tiempo que le lleva a Cloud Spanner aplicar los cambios que derivan de una declaración individual depende de si ese cambio requiere que Cloud Spanner valide los datos o reponer cualquier información. Por ejemplo, si añades la anotación NOT NULL a una columna, Cloud Spanner debe leer todos los valores de los datos de esa columna para poder asegurar que no contiene ningún valor NULL. Este paso puede tardar mucho tiempo si hay que validar una gran cantidad de datos. Otro ejemplo es si se añade un índice a una base de datos: Cloud Spanner rellena el índice usando datos, y ese proceso puede tardar mucho tiempo, según cómo se defina el índice y el tamaño de la tabla base correspondiente. Sin embargo, si añades una nueva columna a una tabla, no habrá que validar ningún dato para que Cloud Spanner pueda realizar el cambio en cuestión de minutos.

En resumen, los cambios de esquema que no requieren que Cloud Spanner valide los datos pueden completarse en cuestión de minutos. Los cambios de esquema que requieren validación pueden llevar más tiempo, en función de la cantidad de datos que deben validarse, pero la validación de datos se realiza en segundo plano sin que afecte al tráfico en tiempo real. Los cambios de esquema que requieren validación de datos se explican con más detalle en la siguiente sección.

Cambios de esquema que requieren validación de datos

Como se explicó anteriormente, Cloud Spanner permite cambiar los esquemas de forma que resulte necesario validar los datos para comprobar que cumplen con las nuevas restricciones. Cuando se ejecuta dicho cambio de esquema, Cloud Spanner no permite que se apliquen cambios de esquema conflictivos en las entidades de esquema afectadas y valida los datos en segundo plano. Si la validación se realiza correctamente, el cambio de esquema se completa de forma adecuada. Si la validación no se realiza correctamente, el cambio de esquema se cancela con un mensaje de error.

Por ejemplo, supongamos que has definido una tabla Songwriters en tu esquema:

CREATE TABLE Songwriters (
  Id         INT64 NOT NULL,
  FirstName  STRING(1024),
  LastName   STRING(1024),
  Nickname   STRING(MAX),
  OpaqueData BYTES(MAX),
) PRIMARY KEY (Id);

Ejemplo de cambios de esquema que requieren validación

Los cambios de esquema siguientes están permitidos, pero requieren validación y puede tardarse en completarlos, en función de la cantidad de datos:

  • Añadir la anotación NOT NULL a una columna de clave no principal. Ejemplo: ALTER TABLE Songwriters ALTER COLUMN Nickname STRING(MAX) NOT NULL

  • Reducir la longitud de una columna. Ejemplo: ALTER TABLE Songwriters ALTER COLUMN FirstName STRING(10)

  • Cambio de BYTES a STRING. Ejemplo: ALTER TABLE Songwriters ALTER COLUMN OpaqueData STRING(MAX)

Es importante tener en cuenta que estos cambios de esquema fallan si los datos subyacentes no satisfacen las necesidades de las nuevas restricciones. Por ejemplo, la declaración ALTER TABLE Songwriters ALTER COLUMN Nickname STRING(MAX) NOT NULL expresada anteriormente causa un error si cualquiera de las columnas Nickname contiene un valor NULL, ya que los datos no cumplen con las restricciones de la nueva definición.

La validación de datos puede tardar desde varios minutos hasta muchas horas. El tiempo para completar la validación de datos depende de estos aspectos:

  • el tamaño del conjunto de datos
  • la cantidad de nodos en la instancia
  • la carga en la instancia

Algunos cambios de esquema pueden alterar el comportamiento de las peticiones a la base de datos antes de que se complete el cambio. Por ejemplo, si añades el valor NOT NULL a una columna, Cloud Spanner comienza a rechazar escrituras de peticiones nuevas que usan el valor NULL en la columna de forma casi inmediata. Si el cambio de esquema nuevo no se realiza correctamente debido a la validación de datos, se mostrará un periodo en el que las escrituras estuvieron bloqueadas incluso si el esquema antiguo las hubiera aceptado.

Puedes cancelar una operación de validación de datos de larga duración mediante el método projects.instances.databases.operations.cancel.

Consejos para actualizar los esquemas

Antes de emitir una actualización de esquema, sigue estos pasos:

  • Verifica que todos los datos en la base de datos que está realizando cambios cumplan con las restricciones impuestas por el cambio de esquema. A continuación se muestran algunos ejemplos habituales:
    • Si añades una anotación NOT NULL a una columna, comprueba que la columna no contiene ningún valor NULL.
    • Si acortas la longitud permitida de una columna de cadena o de bytes, verifica que todos los valores de esa columna cumplan con la restricción de longitud deseada.
  • Recuerda que la realización correcta de una actualización de esquema puede depender de que todos los datos de la base de datos cumplan con la nueva restricción, no solo los datos del esquema que se actualiza. Esto significa que si tienes una base de datos de prueba que usa el mismo esquema que una base de datos de producción, una actualización correcta de la base de datos de prueba no garantiza una actualización correcta de la base de datos de producción.
  • Si estás escribiendo en una columna, tabla o índice que está experimentando un cambio de esquema, asegúrate de que los valores que estás escribiendo cumplan con las nuevas restricciones.
  • Si eliminas una columna, tabla o índice, asegúrate de que no sigues escribiendo ni leyendo.
¿Te ha resultado útil esta página? Enviar comentarios:

Enviar comentarios sobre...

Cloud Spanner Documentation