¿Qué efecto tendrá la reducción del tamaño de una columna varchar en el archivo de base de datos?

15

Tenemos una serie de tablas en nuestra base de datos que tienen VARCHAR(MAX)columnas donde VARCHAR(500)será suficiente un (o algo mucho más pequeño que el máximo). Naturalmente, quiero limpiarlos y reducir el tamaño a niveles más razonables. El 'cómo' hacer esto lo entiendo: mi pregunta es ¿qué hará la alteración de estas columnas en las páginas y los archivos existentes en el disco? (Hay mucha información sobre lo que sucede cuando creces una columna, pero tienes problemas para encontrar información sobre lo que sucede cuando encoges una).

Algunas de las tablas tienen un recuento de filas muy pequeño, por lo que no me preocupa el costo del cambio, pero algunas son bastante grandes y me preocupa que se reorganicen y causen mucho tiempo de bloqueo / inactividad. En términos prácticos, solo quiero una forma de estimar una ventana de mantenimiento. En general, me gustaría entender mejor cómo se comporta el motor de la base de datos en este caso.

¡Gracias por adelantado!

EDITAR:

Estoy viendo 20 tablas, aunque solo la mitad de ellas tienen recuentos de filas superiores a 1,000. El más grande tiene casi un millón de filas. El peor delincuente es una mesa con 350,000 filas y cuatro VARCHAR(MAX)columnas que pueden reducirse al VARCHAR(500)nivel.

nateirvin
fuente

Respuestas:

12

Primero lo primero: ¿Cuántos datos hay en la tabla? ¿Número de filas y tamaño de la tabla?

Segundo: ¿Puede realizar una copia de seguridad y restaurar esta tabla en un servidor de prueba y ejecutar la instrucción alter para ver el impacto (suponiendo que no sea inviable debido a que la tabla es demasiado grande para caber en un sistema que no sea de Producción)? Siempre encuentro que las pruebas en mi entorno son más precisas que los consejos de los interwebs, ya que hay varios factores que pueden influir en el resultado que podrían no proporcionarse en la pregunta simplemente por no saber que esos factores podrían afectar el resultado.

Tercero: aumentar el tamaño de un campo de longitud variable es (suponiendo que no se supere el límite de 8060 bytes) una operación simple de metadatos ya que no cambiarían los datos reales para dicha operación. PERO, por otro lado, reducir el tamaño de un campo de longitud variable, incluso a algo que obviamente funcionará, no es un simple cambio de metadatos porque SQL Server no lo sabe, antes de escanear todas las filas , que el tamaño recién solicitado es válido.

Por lo tanto: Sí, esto bloqueará la mesa por un período de tiempo . ¿Cuanto tiempo? Bueno, aquí está la prueba que acabo de hacer:

Tenía, de algunas otras pruebas, una tabla con un solo INT NOT NULLcampo y 1 millón de filas. Lo copié en una nueva tabla con el fin de hacer esta prueba a través de:

SELECT *, CONVERT(NVARCHAR(MAX), NEWID()) AS [StringField]
INTO dbo.ResizeTest
FROM dbo.ClusteredUnique;

De esta manera, comencé con un escenario similar de tener un MAXcampo (me acabo de dar cuenta de que tienes VARCHARy estoy usando NVARCHAR, pero eso no debería alterar el comportamiento que estoy viendo) al que luego podría cambiar 500. Y tiene datos que pueden caber fácilmente dentro de 500 caracteres. Eso tomó unos minutos.

Entonces corrí:

ALTER TABLE dbo.ResizeTest ALTER COLUMN [StringField] NVARCHAR(500) NULL;

Y eso tomó poco más de 11 minutos.

Acabo de volver a ejecutar la prueba nuevamente, esta vez dejando caer la [ResizeTest]mesa y cambiando ambos NVARCHARs para que sean justos VARCHAR, solo para estar súper seguro de que estoy comparando manzanas con algo que al menos se parece a una manzana ;-).

La creación de la tabla inicial tardó 20 segundos, mientras que la de ALTER TABLE2 minutos.

Entonces, en términos de estimar el tiempo de inactividad, eso es realmente difícil de hacer, ya que se basa en las velocidades de E / S del disco, ya sea que se deban realizar operaciones de crecimiento automático en el archivo de datos y / o el registro de transacciones, etc. es probablemente una gran parte de por qué mi primera prueba tardó 11 minutos en modificarse y la segunda, incluso con la VARCHARmitad del tamaño de los NVARCHARdatos, tomó solo 2 minutos (es decir, los archivos se crecieron previamente en ese punto). Pero aún así, debe tener en cuenta que mi prueba se está ejecutando en mi computadora portátil, que no es el disco más rápido, pero también era solo 1 millón de filas de 2 columnas pequeñas (22 o más bytes por fila).

Y dado que usted preguntó qué le hará a las páginas de datos, aquí está su respuesta. Hice un sp_spaceuseddespués de crear la tabla, después de hacer ALTER COLUMNy después de hacer ALTER TABLE dbo.ResizeTest REBUILD;. Los resultados (los siguientes números se basan en la segunda prueba que usa VARCHAR, no en la primera prueba que usa NVARCHAR):

After initial table creation:        526,344 KB
After ALTER COLUMN VARCHAR(500):   1,031,688 KB  <--- !! Yikes!!
After ALTER REBUILD:                 526,472 KB

Si le preocupa la necesidad de mantener la operación en el menor tiempo posible, consulte un artículo que escribí sobre eso: reestructurar tablas de 100 millones de filas (o más) en segundos. SRSLY! (Se requiere registro gratuito).

Solomon Rutzky
fuente
2
Así que copié la peor tabla en mi instancia local (es decir, un disco más lento y 1/3 de los núcleos). Me ALTERed cada columna en la serie - cada acción se llevó a menos de un segundo. Cuando terminaron, la mesa había duplicado su tamaño, pero una vez que hice una REBUILDoperación (que también fue una operación de menos de un segundo), la mesa volvió a su tamaño original.
nateirvin
@nateirvin Es bueno escuchar eso. Probablemente pueda acelerar la ALTER TABLEoperación haciendo todos los campos de una sola vez, separando cada columna con una coma. Si la transacción es demasiado grande, divida la tabla en 2 declaraciones ALTER de la mitad de las columnas cada una. Y dependiendo de qué tan grande sea la tabla, incluso puede hacer un RECONSTRUCCIÓN entre cada una de las dos declaraciones ALTER. Algo para jugar. Además, tenga en cuenta que la operación probablemente tomará un bloqueo de esquema durante el tiempo que bloqueará todo acceso a la tabla.
Solomon Rutzky
1
Hice cada uno por ALTERseparado para poder rastrear los cambios de tamaño entre cada uno, pero definitivamente es bueno saberlo. ¡Gracias!
nateirvin
1

Por lo que he reunido, ejecutar la instrucción alter no debería llevar mucho tiempo, ya que la mesa no está bloqueada por otro proceso. Según gbn, es solo un cambio de metadatos: /programming/7261909/is-it-bad-to-use-alter-table-to-resize-a-varchar-column-to-a-larger -Talla

Además, en cuanto a cómo se almacena, parece que SQL Server almacenó los datos varchar en una página de 8k hasta que llena una página completa, que en este punto lo reemplaza con un puntero y lo almacena como un BLOB.

Supongo que cuando cambie la longitud, no truncará ningún registro. Si es así, entonces, como máximo, los datos que está convirtiendo a varchar (500) deben tener, como máximo, 502 bytes de longitud y no deben tener un puntero.

Entonces, para resumir, no debería cambiar mucho, siempre y cuando no esté truncando ningún dato.

DForck42
fuente
55
Esto es absolutamente incorrecto. No votaré negativamente porque realmente lo probaste (que es más de lo que algunas personas hacen, así que gracias por hacerlo), pero debes probar esto a escala. La respuesta a la que se vinculó fue sobre aumentar el tamaño, no disminuir. Esas son dos operaciones muy diferentes.
Solomon Rutzky