Spanner vous permet d'effectuer des mises à jour de schéma sans temps d'arrêt. Vous pouvez mettre à jour le schéma d'une base de données existante de plusieurs manières :
Google Cloud Console
Envoyez une commande
ALTER TABLE
sur la page Spanner Studio.Pour accéder à la page Spanner Studio, cliquez sur Spanner Studio dans la page "Présentation de la base de données" ou de la page "Présentation de la table".
À l'aide de l'outil de ligne de commande
gcloud spanner
Envoyez une commande
ALTER TABLE
à l'aide de la méthodegcloud spanner databases ddl update
.À l'aide des bibliothèques clientes
Utiliser l'API REST
projects.instances.databases.updateDdl
À l'aide de l'API RPC
UpdateDatabaseDdl
Mises à jour de schéma compatibles
Spanner accepte les mises à jour de schéma suivantes pour une base de données existante:
- Ajoutez ou supprimez un schéma nommé.
- créer une table ; Les colonnes des nouvelles tables peuvent avoir la valeur
NOT NULL
. - Supprimer une table si elle ne comporte pas de table entrelacée et si elle n'a pas d'index secondaire.
- Créer ou supprimer une table avec une clé étrangère
- Ajouter ou supprimer une clé étrangère dans une table existante.
- Ajouter une colonne non-clé à n'importe quelle table. Les nouvelles colonnes non-clés ne peuvent pas avoir la valeur
NOT NULL
. - Supprimer une colonne non-clé de n'importe quelle table, sauf si elle est utilisée par un index secondaire, une clé étrangère, une colonne générée stockée ou une contrainte de vérification.
- Ajouter
NOT NULL
à une colonne non-clé, à l'exception des colonnesARRAY
. - Supprimer la valeur
NOT NULL
d'une colonne non-clé. - Remplacer une colonne
STRING
par une colonneBYTES
, ou une colonneBYTES
par une colonneSTRING
. - Remplacer une colonne
PROTO
par une colonneBYTES
, ou une colonneBYTES
par une colonnePROTO
. - Modifiez le type de message proto d'une colonne
PROTO
. - Ajoutez des valeurs à une définition
ENUM
et renommez les valeurs existantes à l'aide de la fonctionALTER PROTO BUNDLE
- Modifiez les messages définis dans un
PROTO BUNDLE
de manière arbitraire, à condition que les champs modifiés de ces messages ne soient pas utilisés comme clés dans une table et que les données existantes répondent aux nouvelles contraintes. - Augmenter ou diminuer la longueur maximale d'un type
STRING
ouBYTES
(y compris la valeurMAX
), sauf s'il s'agit d'une colonne de clé primaire héritée d'une ou de plusieurs tables enfants. - Augmentez ou diminuez la limite de longueur pour
ARRAY<STRING>
,ARRAY<BYTES>
, ouARRAY<PROTO>
au maximum autorisé. - Activer ou désactiver les horodatages de commit dans les colonnes de valeur et de clé primaire.
- Ajouter ou supprimer un index secondaire.
- Ajouter ou supprimer une contrainte de vérification dans une table existante.
- Ajouter ou supprimer une colonne générée stockée dans une table existante.
- Créez un nouveau package de statistiques d'optimiseur.
- créer et gérer des vues ;
- Créer et gérer des séquences
- Créez des rôles de base de données et accordez des droits.
- Définissez, modifiez ou supprimez la valeur par défaut d'une colonne.
- Modifiez les options de la base de données (
default_leader
ouversion_retention_period
, par exemple). - créer et gérer des flux de modifications ;
- Créer et gérer des modèles de ML
Mises à jour de schéma non compatibles
Spanner n'est pas compatible avec les mises à jour de schéma suivantes pour une base de données existante :
- Si un champ
PROTO
de typeENUM
est référencé par une clé de table ou d'index, vous ne pouvez pas supprimer les valeursENUM
du fichier proto et les énumérations. (La suppression des valeursENUM
des énumérations utilisées par les colonnesENUM<>
est possible, y compris lorsque ces colonnes sont utilisées comme clés.)
Performances de la mise à jour de schéma
Les mises à jour de schéma dans Spanner ne nécessitent pas de temps d'arrêt. Lorsque vous soumettez un lot d'instructions DDL à une base de données Spanner, vous pouvez continuer à écrire et à lire dans la base de données sans interruption, pendant que Spanner applique la mise à jour en tant qu'opération de longue durée.
La durée d'exécution d'une instruction DDL varie en fonction de la nécessité de valider les données existantes ou de remplir des données. Par exemple, si vous ajoutez l'annotation NOT NULL
à une colonne existante, Spanner doit lire toutes les valeurs de la colonne pour s'assurer qu'elle ne contient aucune valeur NULL
. Cette étape peut être longue s'il y a beaucoup de données à valider. Prenons comme autre exemple l'ajout d'un index à une base de données : Spanner remplit l'index à l'aide des données existantes. Ce processus peut durer longtemps en fonction de la manière dont est défini l'index et de la taille de la table de base correspondante. Toutefois, si vous ajoutez une colonne à un tableau,
aucune donnée existante à valider. Spanner peut donc effectuer
rapidement.
En résumé, les mises à jour de schéma ne nécessitant pas de validation par Spanner les données existantes peuvent être réalisées en quelques minutes. Les mises à jour de schéma nécessitant une validation peuvent prendre plus longtemps, en fonction de la quantité de données existantes à valider. Cependant, la validation des données s'effectue en arrière-plan avec une priorité moindre que celle du trafic de production. Les mises à jour de schéma nécessitant une validation des données sont abordées plus en détail dans la section suivante.
Mises à jour de schéma validées par rapport aux définitions de vue
Lorsque vous effectuez une mise à jour de schéma, Spanner vérifie que la mise à jour n'invalide pas les requêtes utilisées pour définir les vues existantes. Si la validation réussit, la mise à jour du schéma réussit. Si la validation échoue, la mise à jour du schéma échoue. Consultez la section Bonnes pratiques lors de la création de vues pour plus de détails.
Mises à jour de schéma nécessitant une validation des données
Certaines mises à jour de schéma nécessitent de vérifier que les données existantes répondent aux nouvelles contraintes. Lorsqu'une mise à jour de schéma nécessite la validation des données, Spanner interdit les mises à jour de schéma en conflit avec le schéma concerné et valide les données en arrière-plan. Si la validation réussit, la mise à jour du schéma réussit. Si la validation échoue, la mise à jour du schéma échoue également. Les opérations de validation sont exécutées comme des opérations de longue durée. Vous pouvez vérifier le statut de ces opérations pour savoir si elles ont réussi ou échoué.
Par exemple, supposons que vous ayez défini le fichier music.proto
suivant avec une
Énumération RecordLabel
et message de protocole Songwriter
:
enum RecordLabel {
COOL_MUSIC_INC = 0;
PACIFIC_ENTERTAINMENT = 1;
XYZ_RECORDS = 2;
}
message Songwriter {
required string nationality = 1;
optional int64 year_of_birth = 2;
}
Pour ajouter une table Songwriters
à votre schéma, procédez comme suit:
GoogleSQL
CREATE PROTO BUNDLE (
googlesql.example.music.Songwriter,
googlesql.example.music.RecordLabel,
);
CREATE TABLE Songwriters (
Id INT64 NOT NULL,
FirstName STRING(1024),
LastName STRING(1024),
Nickname STRING(MAX),
OpaqueData BYTES(MAX),
SongWriter googlesql.example.music.Songwriter
) PRIMARY KEY (Id);
CREATE TABLE Albums (
SongwriterId INT64 NOT NULL,
AlbumId INT64 NOT NULL,
AlbumTitle STRING(MAX),
Label INT32
) PRIMARY KEY (SongwriterId, AlbumId);
Les mises à jour de schéma suivantes sont autorisées, mais elles nécessitent une validation et peuvent durer longtemps selon la quantité de données existantes :
Ajouter la valeur
NOT NULL
à une colonne non-clé. Exemple :ALTER TABLE Songwriters ALTER COLUMN Nickname STRING(MAX) NOT NULL;
Réduire la longueur d'une colonne. Exemple :
ALTER TABLE Songwriters ALTER COLUMN FirstName STRING(10);
Remplacer le type
BYTES
parSTRING
. Exemple :ALTER TABLE Songwriters ALTER COLUMN OpaqueData STRING(MAX);
Remplacer le type
INT64/INT32
parENUM
. Exemple :ALTER TABLE Albums ALTER COLUMN Label googlesql.example.music.RecordLabel;
Suppression des valeurs existantes de la définition d'énumération
RecordLabel
.Activer les horodatages de commit sur une colonne
TIMESTAMP
existante. Exemple :ALTER TABLE Albums ALTER COLUMN LastUpdateTime SET OPTIONS (allow_commit_timestamp = true);
Ajouter une contrainte de vérification à une table existante.
Ajouter une colonne générée stockée à une table existante.
Créer une nouvelle table avec une clé étrangère.
Ajouter une clé étrangère à une table existante.
Ces mises à jour de schéma échouent si les données sous-jacentes ne répondent pas aux nouvelles contraintes. Par exemple, l'instruction ALTER TABLE Songwriters ALTER COLUMN Nickname
STRING(MAX) NOT NULL
échoue si la colonne Nickname
contient NULL
, car les données existantes ne respectent pas la contrainte NOT NULL
de la nouvelle définition.
La validation des données peut prendre de quelques minutes à plusieurs heures. Le temps nécessaire à cette validation dépend des éléments suivants :
- Taille de l'ensemble de données
- La capacité de calcul de l'instance
- La charge sur l'instance
Certaines mises à jour de schéma peuvent modifier le comportement des requêtes adressées à la base de données avant la fin de la mise à jour. Par exemple, si vous ajoutez NOT NULL
à une
Spanner commence presque immédiatement à rejeter les écritures pour
Requêtes qui utilisent NULL
pour la colonne. Si finalement la mise à jour du nouveau schéma échoue lors de la validation des données, il y aura eu une période pendant laquelle les écritures auront été bloquées, même si l'ancien schéma les avait acceptées.
Vous pouvez annuler une opération de validation des données de longue durée à l'aide de la méthode projects.instances.databases.operations.cancel
ou en utilisant gcloud spanner operations
.
Ordre d'exécution des instructions dans les lots
Si vous utilisez la Google Cloud CLI, l'API REST ou l'API RPC, vous pouvez émettre un lot d'une ou plusieurs instructions CREATE
, ALTER
ou DROP
.
Spanner applique les instructions d'un même lot dans l'ordre, en s'arrêtant première erreur. Si l'application d'une instruction entraîne une erreur, cette instruction est annulée. Les instructions du lot précédemment appliquées ne sont en revanche pas annulées.
Spanner peut combiner et réorganiser des instructions de différents lots,
potentiellement mélanger des instructions de
différents lots en une seule modification atomique qui
est appliquée à la base de données. Au sein de chaque modification atomique, les instructions des différents lots se déroulent dans un ordre arbitraire. Par exemple, si un lot d'instructions
contient ALTER TABLE MyTable ALTER COLUMN MyColumn STRING(50)
et un autre
le lot d'instructions contient ALTER TABLE MyTable ALTER COLUMN MyColumn
STRING(20)
, Spanner laisse cette colonne dans l'un de ces deux états,
mais il n'est pas
spécifié lequel.
Versions de schéma créées lors des mises à jour de schéma
Spanner utilise la gestion des versions de schéma pour éviter tout temps d'arrêt pendant la mise à jour du schéma dans une base de données volumineuse. Spanner conserve l'ancien schéma pour permettre les lectures pendant le traitement de la mise à jour du schéma. Spanner Ensuite, il crée une ou plusieurs versions du schéma pour le traiter. mise à jour. Chaque version contient le résultat d'un ensemble d'instructions dans une modification atomique unique.
Chaque version de schéma ne correspond pas nécessairement à un lot d'instructions DDL ou à une instruction DDL individuelle. Certaines instructions LDD individuelles, comme la création d'index pour les tables de base existantes ou les instructions nécessitant une validation des données, génèrent plusieurs versions de schéma. Dans d'autres cas, plusieurs instructions DDL peuvent être regroupées dans une même version. Les anciennes versions de schéma consomment d'importantes ressources de serveur et de stockage, et sont conservées jusqu'à ils expirent (plus besoin de diffuser des lectures de versions antérieures des données).
Le tableau suivant indique le temps nécessaire à Spanner pour mettre à jour un schéma.
Opération sur le schéma | Durée approximative |
---|---|
CREATE TABLE |
Minutes |
CREATE INDEX |
Quelques minutes, voire plusieurs heures, si la table de base est créée avant l'index. Quelques minutes, si l'instruction est exécutée en même temps que l'instruction |
DROP TABLE |
Minutes |
DROP INDEX |
Minutes |
ALTER TABLE ... ADD COLUMN |
Minutes |
ALTER TABLE ... ALTER COLUMN |
Quelques minutes, voire plusieurs heures, si une validation en arrière-plan est nécessaire. Quelques minutes, si la validation en arrière-plan n'est pas requise. |
ALTER TABLE ... DROP COLUMN |
Minutes |
ANALYZE |
Quelques minutes à quelques heures, selon la taille de la base de données. |
Modifications des types de données et flux de modifications
Si vous modifiez le type de données d'une colonne surveillée par un flux de modifications, le champ column_types
des enregistrements de flux de modifications ultérieurs pertinents reflète son nouveau type, tout comme les données JSON old_values
dans le champ mods
des enregistrements.
Le new_values
du champ mods
d'un enregistrement de flux de modifications correspond toujours au type actuel d'une colonne. La modification du type de données d'une colonne surveillée
affecter les enregistrements de flux de
modifications antérieurs à ce changement.
Dans le cas particulier d'un passage de BYTES
à STRING
,
Spanner valide les anciens composants de la colonne
valeurs lors de la mise à jour du schéma.
Par conséquent, Spanner a décodé de manière sécurisée
des valeurs de type BYTES
dans des chaînes au moment où il écrit l'ensemble des
les enregistrements de flux de modifications.
Bonnes pratiques pour les mises à jour de schéma
Les sections suivantes décrivent les recommandations pour la mise à jour des schémas.
Procédures à suivre avant de lancer la mise à jour de schéma
Avant de lancer une mise à jour de schéma :
Vérifiez que toutes les données existantes dans la base de données que vous modifiez respectent les contraintes imposées par la mise à jour du schéma. Étant donné que la réussite de certains types de mise à jour de schéma dépend des données de la base de données et pas seulement de son schéma actuel, une mise à jour de schéma réussie sur une base de test ne garantit pas la réussite de la mise à jour de schéma sur une base de production. Voici quelques exemples courants :
- Si vous ajoutez une annotation
NOT NULL
à une colonne existante, vérifiez qu'elle ne contient aucune valeurNULL
. - Si vous réduisez la longueur autorisée d'une colonne
STRING
ouBYTES
, vérifiez que toutes les valeurs existantes de cette colonne respectent la longueur d'une contrainte.
- Si vous ajoutez une annotation
Si vous écrivez dans une colonne, une table ou un index qui doit subir une mise à jour de schéma, assurez-vous que les valeurs que vous ajoutez répondent aux nouvelles contraintes.
Si vous supprimez une colonne, une table ou un index, assurez-vous de ne pas continuer à l'utiliser en lecture ou en écriture.
Limiter la fréquence des mises à jour de schéma
Si vous effectuez trop de mises à jour de schéma en peu de temps, Spanner
peut throttle
le
le traitement des mises à jour
de schéma en file d'attente. Ceci est dû au fait que Spanner limite la quantité d'espace disponible pour le stockage des versions de schéma. La mise à jour de votre schéma peut être limitée si la période de conservation comporte trop d'anciennes versions de schéma. Le taux maximal de modifications de schéma dépend de nombreux facteurs, dont l'un est le nombre total de colonnes dans la base de données. Par exemple, un
base de données contenant 2 000 colonnes (environ 2 000 lignes dans
INFORMATION_SCHEMA.COLUMNS
)
peut effectuer 1 500 modifications de schéma au maximum (moins de 1 500 modifications du schéma
modification nécessite plusieurs versions) au cours de la période de conservation. Pour afficher l'état des mises à jour de schéma en cours, utilisez la commande gcloud spanner operations list
et filtrez les opérations de type DATABASE_UPDATE_DDL
. Pour annuler une mise à jour de schéma en cours, exécutez la commande gcloud spanner operations cancel
et spécifiez l'ID d'opération.
La manière dont vos instructions LDD sont regroupées et leur ordre dans chaque lot peuvent affecter le nombre de versions de schéma qui en résultent. Pour optimiser le nombre de mises à jour de schéma que vous pouvez effectuer sur une période donnée, il est conseillé d'utiliser un traitement par lots qui réduit le nombre de versions de schéma. Quelques règles de base sont décrites dans la section Mises à jour volumineuses.
Comme décrit dans la section Versions de schéma, certaines instructions LDD créent plusieurs versions de schéma. Celles-ci sont importantes pour le traitement par lot et l'ordre dans chaque lot. Deux principaux types d'instructions permettent de créer plusieurs versions de schéma :
- Les instructions pouvant nécessiter un remplissage des données d'index, telles que
CREATE INDEX
- Les instructions pouvant nécessiter la validation des données existantes, comme l'ajout de
NOT NULL
Cependant, ces types d'instructions ne créent pas toujours plusieurs versions de schéma. Spanner essaie de détecter si ces types d'instructions
optimisé pour éviter d'utiliser plusieurs versions de schéma, qui dépendent du traitement par lot.
Par exemple, une instruction CREATE INDEX
se produit dans le même lot qu'un
Instruction CREATE TABLE
pour la table de base de l'index, sans interactivité
pour les autres tables, évite d'avoir à remplir les données d'index.
car Spanner peut garantir que la table de base est vide au moment
l'index est créé. La section Mises à jour volumineuses explique comment utiliser cette propriété pour créer efficacement de nombreux index.
Si vous ne pouvez pas grouper vos instructions LDD pour éviter de créer de nombreuses versions de schéma, vous devez limiter le nombre de mises à jour de schéma pour un même schéma de base de données pendant sa période de conservation. Augmentez la fenêtre temporelle dans laquelle vous effectuez les mises à jour de schéma pour permettre à Spanner de supprimer les versions antérieures du schéma avant d'en créer de nouvelles.
- Pour certains systèmes de gestion de bases de données relationnelles, il existe des packages logiciels qui effectuent toute une série de mises à jour de schéma (vers une version ultérieure ou antérieure) sur la base de données lors de chaque déploiement en production. Ces types de processus ne sont pas recommandés pour Spanner.
- Spanner est optimisé pour utiliser des clés primaires afin de partitionner les données pour des solutions d'architecture mutualisée. Les solutions d'architecture mutualisée qui utilisent des tables distinctes pour chaque client peuvent générer beaucoup d'attente dans le traitement des opérations de mise à jour de schéma, occasionnant un temps de traitement important.
- Les mises à jour de schéma nécessitant une validation ou un remplissage d'index utilisent davantage de ressources de serveur, car chaque instruction crée plusieurs versions du schéma en interne.
Options pour les mises à jour de schéma volumineuses
La meilleure façon de créer une table et un grand nombre d'index sur cette table est de les créer tous en même temps, de sorte qu'une seule version de schéma soit créée. Il est recommandé de créer les index immédiatement après la table dans la liste des instructions LDD. Vous pouvez créer la table et ses index lors de la création de la base de données ou via un seul grand groupe d'instructions. Si vous devez créer plusieurs tables, chacune avec de nombreux index, vous pouvez inclure toutes les instructions dans un seul lot. Vous pouvez inclure plusieurs milliers d'instructions dans un seul lot lorsque toutes les instructions peuvent être exécutées ensemble à l'aide d'une seule version de schéma.
Lorsqu'une instruction nécessite un remplissage des données d'index ou une validation de données, elle ne peut pas être exécutée dans une seule version de schéma. Cela se produit pour les instructions CREATE INDEX
lorsque la table de base de l'index existe déjà (soit parce qu'elle a été créée dans un lot d'instructions LDD précédent, soit parce qu'une instruction du lot entre les instructions CREATE TABLE
et CREATE INDEX
nécessitait plusieurs versions de schéma. Spanner nécessite qu'il n'y ait
plus de 10 instructions de ce type dans un seul lot. La création d'index nécessitant un remplissage, en particulier, utilise plusieurs versions de schéma par index. Il est donc recommandé de ne pas créer plus de trois nouveaux index nécessitant un remplissage par jour (quelle que soit la manière dont ils sont regroupés, à moins que ce regroupement ne permette d'éviter le remplissage).
Par exemple, ce lot d'instructions utilisera une seule version de schéma :
GoogleSQL
CREATE TABLE Singers ( SingerId INT64 NOT NULL, FirstName STRING(1024), LastName STRING(1024), ) PRIMARY KEY (SingerId); CREATE INDEX SingersByFirstName ON Singers(FirstName); CREATE INDEX SingersByLastName ON Singers(LastName); CREATE TABLE Albums ( SingerId INT64 NOT NULL, AlbumId INT64 NOT NULL, AlbumTitle STRING(MAX), ) PRIMARY KEY (SingerId, AlbumId); CREATE INDEX AlbumsByTitle ON Albums(AlbumTitle);
En revanche, ce lot utilisera de nombreuses versions de schéma, car UnrelatedIndex
nécessite un remplissage (puisque sa table de base doit avoir déjà existé), ce qui oblige tous les index suivants à nécessiter également un remplissage (même s'ils font partie du même lot que leurs tables de base) :
GoogleSQL
CREATE TABLE Singers ( SingerId INT64 NOT NULL, 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); CREATE INDEX UnrelatedIndex ON UnrelatedTable(UnrelatedIndexKey); CREATE INDEX SingersByFirstName ON Singers(FirstName); CREATE INDEX SingersByLastName ON Singers(LastName); CREATE INDEX AlbumsByTitle ON Albums(AlbumTitle);
Il est préférable de déplacer la création de UnrelatedIndex
à la fin du lot, ou vers un autre lot, afin de réduire les versions de schéma.
Attendre que les demandes d'API soient terminées
Lorsque vous effectuez des requêtes projects.instances.databases.updateDdl
(API REST) ou UpdateDatabaseDdl
(API RPC), utilisez projects.instances.databases.operations.get
(API REST) ou GetOperation
(API RPC), respectivement, pour attendre que chaque requête soit terminée avant d'en lancer une nouvelle. En attendant la fin de chaque requête, votre application peut suivre la progression de vos mises à jour de schéma. Cela permet également de conserver le volume des mises à jour de schéma en attente à une taille raisonnable.
Chargement groupé
Si vous effectuez un chargement groupé des données dans vos tables après leur création, il est généralement plus efficace de créer des index une fois les données chargées. Si vous ajoutez plusieurs index, il peut être plus efficace de créer la base de données avec tous les index et toutes les tables du schéma initial, comme décrit dans les options pour les mises à jour volumineuses.