La seule façon sensée de mettre à jour une table de 120 millions d'enregistrements est d'utiliser un SELECT
déclaration qui remplit une seconde table. Vous devez faire attention lorsque vous faites cela. Instructions ci-dessous.
Cas simple
Pour une table sans index clusterisé, pendant une période sans DML simultané :
SELECT *, new_col = 1 INTO clone.BaseTable FROM dbo.BaseTable
- recréer des index, des contraintes, etc. sur une nouvelle table
- changez l'ancien et le nouveau avec ALTER SCHEMA ... TRANSFER.
- supprimer l'ancienne table
Si vous ne pouvez pas créer de schéma clone, un nom de table différent dans le même schéma fera l'affaire. N'oubliez pas de renommer toutes vos contraintes et déclencheurs (le cas échéant) après le changement.
Cas non simple
Tout d'abord, recréez votre BaseTable
avec le même nom sous un schéma différent, par exemple clone.BaseTable
. L'utilisation d'un schéma séparé simplifiera le processus de renommage ultérieur.
- Inclure l'index clusterisé , le cas échéant. N'oubliez pas que les clés primaires et les contraintes uniques peuvent être regroupées, mais pas nécessairement.
- Inclure des colonnes d'identité et des colonnes calculées , le cas échéant.
- Incluez votre nouvelle colonne INT , où qu'il soit.
- Ne pas inclure l'un des éléments suivants :
- déclencheurs
- contraintes de clé étrangère
- index non clusterisés/clés primaires/contraintes uniques
- vérifier les contraintes ou les contraintes par défaut. Les valeurs par défaut ne font pas beaucoup de différence, mais nous essayons de garder les choses au minimum.
Ensuite, testez votre insert avec 1 000 lignes :
-- assuming an IDENTITY column in BaseTable
SET IDENTITY_INSERT clone.BaseTable ON
GO
INSERT clone.BaseTable WITH (TABLOCK) (Col1, Col2, Col3)
SELECT TOP 1000 Col1, Col2, Col3 = -1
FROM dbo.BaseTable
GO
SET IDENTITY_INSERT clone.BaseTable OFF
Examinez les résultats. Si tout apparaît dans l'ordre :
- tronquer la table de clonage
- Assurez-vous que la base de données est enregistrée en bloc ou dans un modèle de récupération simple
- effectuer l'insertion complète.
Cela prendra un certain temps, mais pas autant qu'une mise à jour. Une fois terminé, vérifiez les données dans la table de clonage pour vous assurer que tout est correct.
Ensuite, recréez toutes les clés primaires/contraintes uniques/index et contraintes de clé étrangère non clusterisées (dans cet ordre). Recréez les contraintes par défaut et vérifiez, le cas échéant. Recréez tous les déclencheurs. Recréez chaque contrainte, index ou déclencheur dans un lot séparé. ex :
ALTER TABLE clone.BaseTable ADD CONSTRAINT UQ_BaseTable UNIQUE (Col2)
GO
-- next constraint/index/trigger definition here
Enfin, déplacez dbo.BaseTable
à un schéma de sauvegarde et clone.BaseTable
au schéma dbo (ou partout où votre table est censée vivre).
-- -- perform first true-up operation here, if necessary
-- EXEC clone.BaseTable_TrueUp
-- GO
-- -- create a backup schema, if necessary
-- CREATE SCHEMA backup_20100914
-- GO
BEGIN TRY
BEGIN TRANSACTION
ALTER SCHEMA backup_20100914 TRANSFER dbo.BaseTable
-- -- perform second true-up operation here, if necessary
-- EXEC clone.BaseTable_TrueUp
ALTER SCHEMA dbo TRANSFER clone.BaseTable
COMMIT TRANSACTION
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE() -- add more info here if necessary
ROLLBACK TRANSACTION
END CATCH
GO
Si vous avez besoin de libérer de l'espace disque, vous pouvez supprimer votre table d'origine à ce stade, mais il peut être prudent de la conserver un peu plus longtemps.
Inutile de dire qu'il s'agit idéalement d'un site hors ligne opération. Si des personnes modifient des données pendant que vous effectuez cette opération, vous devrez effectuer une opération de mise à niveau avec le commutateur de schéma. Je recommande de créer un déclencheur sur dbo.BaseTable
pour consigner tous les DML dans une table distincte. Activez ce déclencheur avant de commencer l'insertion. Ensuite, dans la même transaction que vous effectuez le transfert de schéma, utilisez la table de journal pour effectuer un true-up. Testez ceci d'abord sur un sous-ensemble de données ! Les deltas sont faciles à bousiller.