sql >> Base de Datos >  >> RDS >> Sqlserver

Estrechamiento de los tipos de datos en una tabla muy grande

En primer lugar, gracias por hacer esto. Es una victoria tan obvia que muchos no verían mucho valor en ella, pero valdrá la pena :). Hacer que el mundo sea un poco más cuerdo.

Con respecto a IsActive siendo un booleano. Supongo que estás pensando en convertirlo en un BIT campo. Ese podría ser el camino a seguir, pero a veces es mejor ir con TINYINT ya que existe la posibilidad de ampliar el significado a más de 2 estados. En cuyo caso, realmente se convierte más en StatusID . Por lo general, es un caso de algo que comienza de manera simplista como Activo / Inactivo , pero más adelante quizás Eliminado y/u otros. Desde una perspectiva de tamaño, TINYINT siempre es de 1 byte. Por otro lado, BIT es 1 byte para hasta 8 BIT campos . Es decir, un BIT el campo es 1 byte, 2 BIT campos también es un byte, y así sucesivamente hasta 8 BIT campos que se almacenan en un solo byte. Por lo tanto, no se ahorra espacio eligiendo BIT sobre TINYINT cuando la tabla solo tiene 1 BIT campo. Solo algo a tener en cuenta.

Hacer una ALTER TABLE es demasiado para una mesa grande, como viste. Una opción, aunque no muy buena, es agregar un NOT NULL campo--Number_1new --con un DEFAULT valor (esto será instantáneo debido al valor predeterminado, al menos comenzando con SQL 2012) que ninguno de ellos tendría naturalmente (por ejemplo, 255), y luego migrando lentamente los valores, en un bucle, como en:

UPDATE TOP (5000) tab
SET tab.Number_1new = tab.Number_1
FROM [table] tab
WHERE tab.Number_1new = 255;

Y cuando haya terminado, haga:

sp_rename 'table.Number_1', 'Number_1old', 'COLUMN';
sp_rename 'table.Number_1new', 'Number_1', 'COLUMN';

Por supuesto, es mejor envolver eso en una TRANSACCIÓN, y eso envuelto en TRY / CATCH. Cuando el código relacionado se haya actualizado y todo se haya probado y los datos se vean bien, puede eliminar el Number_1old columna.

Sin embargo, la mejor manera que he encontrado es crear una nueva tabla, hacer una transición lenta de los datos y luego intercambiar las tablas y el código al mismo tiempo. Detallé los pasos en un artículo sobre SQL Server Central:Reestructurar 100 millones de filas (o más) Tablas en Segundos. SRSLY! (se requiere registro gratuito). En caso de que haya problemas para acceder a ese artículo, estos son los pasos básicos:

  1. Cree una nueva tabla con la estructura ideal:[tableNew]. Si está en Enterprise Edition, considere habilitar la compresión ROW o PAGE, ya que a veces pueden ayudar. Pero primero investigue un poco, ya que hay algunas situaciones en las que tienen un efecto negativo. Hay documentación en MSDN para ayudarlo a resolverlo, así como algunas herramientas para ayudar a estimar el ahorro potencial. Pero incluso si habilita la compresión, no vería esa acción como un reemplazo del proyecto que está haciendo aquí.
  2. Agregue un activador AFTER UPDATE, DELETE en [tabla] para mantener los cambios sincronizados (pero no hay necesidad de preocuparse por las nuevas filas)
  3. Cree un trabajo del Agente SQL que mueva las filas faltantes en lotes. Haga esto en un ciclo que hace un INSERT INTO [tableNew] (Columns) SELECT TOP (n) Columns FROM [table] WHERE ?? ORDER BY ??
  4. Las cláusulas WHERE y ORDER BY dependen de la situación. Deben estar orientados a hacer el mejor uso del índice agrupado. Si el índice agrupado de la nueva tabla es estructuralmente el mismo que el de la tabla anterior/actual, al comienzo de cada bucle puede obtener el MAX([id]) de [tableNew] y usarlo para obtener la tabla WHERE table.[id] > @MaxIdInTableNew ORDER BY table.[id] .
  5. Cree la nueva tabla, active la tabla actual y el trabajo del Agente SQL aproximadamente una semana antes de que necesite realizar la transición completa. Ese marco de tiempo puede cambiar según su situación, pero asegúrese de darse suficiente tiempo. Es mucho mejor para el trabajo terminar de migrar las filas y solo tener unas pocas ingresando a la vez en lugar de estar a 100 000 del conjunto completo cuando se supone que debe comenzar el lanzamiento.
  6. Si el plan es migrar las otras tablas relacionadas (las referencias de PK para los dos FK que desea convertir en INT s), luego haga esos campos aquí INT ahora y simplemente no agregue el FK hasta que esas otras tablas se migren para tener campos INT como sus PK. No desea tener que reconstruir esta tabla nuevamente solo para realizar ese cambio en los campos FK.
  7. Durante el corte (en un TRY/CATCH, por supuesto):
    1. COMENZAR TRAN
    2. haga un recuento final de filas en ambas tablas para asegurarse de que todo se mueva (es posible que desee verificar la cordura de las filas antes del lanzamiento para asegurarse de que el activador realizó las actualizaciones y eliminaciones como se esperaba)
    3. cambiar el nombre de la tabla actual a "antiguo"
    4. cambie el nombre de la tabla "nueva" para que no tenga "nueva"
    5. eliminar el trabajo del Agente SQL (o al menos deshabilitarlo)
    6. renombrar objetos dependientes como restricciones, etc.
    7. COMPROMISO