La única forma correcta de actualizar una tabla de registros de 120M es con una declaración SELECT
que rellena una segunda tabla. Tienes que tener cuidado al hacer esto. Instrucciones a continuación.
SELECT *, new_col = 1 INTO clone.BaseTable FROM dbo.BaseTable
- índices recrear restricciones, etc. en la nueva tabla
- cambiar antiguo y nuevo con ALTER SCHEMA ... TRANSFER.
- caída de la mesa de edad
Si no puede crear un esquema clon, un nombre de tabla diferente en el mismo esquema va a hacer. Recuerde cambiar el nombre de todas sus restricciones y factores desencadenantes (si corresponde) después del cambio.
Caso no sencilla
En primer lugar, volver a crear su BaseTable
con el mismo nombre bajo un esquema diferente, por ejemplo clone.BaseTable
. Usar un esquema separado simplificará el proceso de cambio de nombre más adelante.
- incluir el índice agrupado, en su caso. Recuerde que las claves principales y las restricciones únicas pueden agruparse, pero no necesariamente.
- Incluya columnas de identidad y columnas calculadas, si corresponde.
- Incluya su nueva columna INT, donde corresponda.
- No incluya cualquiera de los siguientes:
- desencadena
- restricciones de clave externa
- índices no agrupados llaves/primaria/restricciones únicas
- restricciones de comprobación o restricciones predeterminadas. Los valores predeterminados no hacen mucha diferencia, pero estamos tratando de mantener cosas mínimas.
Entonces, prueba de su inserción w/1000 filas:
-- 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
examinar los resultados. Si todo parece en orden:
- truncar la tabla clon
- asegúrese de que la base de datos en el modelo de cargas masivas de registros o de recuperación simple
- realizar la inserción completa.
Esto llevará un tiempo, pero no tanto como una actualización. Una vez que se completa, verifique los datos en la tabla de clonación para asegurarse de que todo sea correcto.
A continuación, vuelva a crear todas las claves primarias no agrupadas/restricciones/índices únicos y restricciones de clave externa (en ese orden). Recrear valores predeterminados y verificar restricciones, si corresponde. Recrear todos los factores desencadenantes. Vuelva a crear cada restricción, índice o activador en un lote por separado. por ejemplo:
ALTER TABLE clone.BaseTable ADD CONSTRAINT UQ_BaseTable UNIQUE (Col2)
GO
-- next constraint/index/trigger definition here
Por último, se mueven dbo.BaseTable
a un esquema de copia de seguridad y clone.BaseTable
al esquema dbo (o donde quiera que su tabla se supone que vive).
-- -- 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 necesita liberar espacio en disco, puede caer la tabla original en este momento, aunque puede ser prudente para mantenerlo en torno a un poco más de tiempo.
No hace falta decir que esto es idealmente una operación sin conexión. Si tiene personas que modifican datos mientras realiza esta operación, deberá realizar una operación de actualización con el cambio de esquema. Recomiendo crear un disparador en dbo.BaseTable
para registrar todos los DML en una tabla separada. Habilite este disparador antes de comenzar la inserción. Luego, en la misma transacción en la que realiza la transferencia de esquema, use la tabla de registro para realizar un true-up. ¡Pruebe esto primero en un subconjunto de datos! Los deltas son fáciles de arruinar.
El problema está basado en IO. Remus abordó este problema aquí: http://stackoverflow.com/questions/3523831/update-statement-running-for-too-long-or-not/3523903#3523903 –
Me preocupaba que pudiera estar basado en IO. Lamentablemente, no hay mucho que pueda hacer al respecto. ¿Los lotes incrementales más pequeños funcionarán más rápido? –
No. El volumen de datos general será el mismo: páginas actualizadas y páginas de registro. Todavía son 120 millones de filas, y esas filas efectivamente se escriben dos veces (una para el registro y otra para la tienda de respaldo). Entonces, el tiempo debe ser proporcional al tamaño total de su mesa. Si se trata de una tabla con un solo byte de 4 bytes, eso equivale a 1G de datos para escribir (120 * 4 = 480, * 2 - 960). Entonces, ¿qué tan grande es la mesa en general? –