Tengo una pregunta sobre el ALTER TABLE
comando en una tabla realmente grande (casi 30 millones de filas). Una de sus columnas es a varchar(255)
y me gustaría cambiar su tamaño a a varchar(40)
. Básicamente, me gustaría cambiar mi columna ejecutando el siguiente comando:
ALTER TABLE mytable ALTER COLUMN mycolumn TYPE varchar(40);
No tengo ningún problema si el proceso es muy largo, pero parece que mi tabla ya no es legible durante el comando ALTER TABLE. ¿Hay una manera más inteligente? ¿Quizás agregar una nueva columna, copiar valores de la columna anterior, soltar la columna antigua y finalmente cambiar el nombre de la nueva?
Cualquier pista será muy apreciada! Gracias por adelantado,
Nota: Yo uso PostgreSQL 9.0.
postgresql
varchar
alter-table
Laberinto
fuente
fuente
resizing
eso no hará que la mesa ocupe menos espacio?varchar(255)
a PostgreSQL, entonces no asignará 255 bytes para un valor cuya longitud real es 40 bytes. Asignará 40 bytes (más algunos gastos generales internos). Lo único quebe changed by the
ALTERARÁ LA TABLA` es el número máximo de bytes que puede almacenar en esa columna sin que PG obtenga un error.Respuestas:
Hay una descripción de cómo hacer esto en Cambiar el tamaño de una columna en una tabla PostgreSQL sin cambiar los datos . Tienes que hackear los datos del catálogo de la base de datos. La única forma de hacerlo oficialmente es ALTER TABLE, y como has notado, el cambio bloqueará y reescribirá toda la tabla mientras se ejecuta.
Asegúrese de leer la sección Tipos de caracteres de los documentos antes de cambiar esto. Todo tipo de casos extraños a tener en cuenta aquí. La verificación de longitud se realiza cuando los valores se almacenan en las filas. Si piratea un límite inferior allí, eso no reducirá en absoluto el tamaño de los valores existentes. Sería aconsejable hacer un análisis de toda la tabla en busca de filas donde la longitud del campo es> 40 caracteres después de realizar el cambio. Tendrá que encontrar la forma de truncarlos manualmente, para que pueda recuperar algunos bloqueos solo en los de gran tamaño, porque si alguien intenta actualizar algo en esa fila, lo rechazará como demasiado grande ahora, en ese momento se va a almacenar la nueva versión de la fila. Se produce hilaridad para el usuario.
VARCHAR es un tipo terrible que existe en PostgreSQL solo para cumplir con su parte terrible asociada del estándar SQL. Si no le importa la compatibilidad con múltiples bases de datos, considere almacenar sus datos como TEXTO y agregue una restricción para limitar su longitud. Las restricciones que puede cambiar sin este problema de bloqueo / reescritura de la tabla, y pueden hacer más verificaciones de integridad que solo la verificación de longitud débil.
fuente
En PostgreSQL 9.1 hay una manera más fácil
http://www.postgresql.org/message-id/[email protected]
fuente
Ok, probablemente llegue tarde a la fiesta, PERO ...
¡NO HAY NECESIDAD DE REDimensionAR LA COLUMNA EN SU CASO!
Postgres, a diferencia de otras bases de datos, es lo suficientemente inteligente como para usar solo el espacio suficiente para acomodar la cadena (incluso usando compresión para cadenas más largas), por lo que incluso si su columna se declara como VARCHAR (255), si almacena cadenas de 40 caracteres en la columna, el uso del espacio será de 40 bytes + 1 byte de sobrecarga.
( http://www.postgresql.org/docs/9.0/interactive/datatype-character.html )
La especificación de tamaño en VARCHAR solo se usa para verificar el tamaño de los valores que se insertan, no afecta el diseño del disco. De hecho, los campos VARCHAR y TEXT se almacenan de la misma manera en Postgres .
fuente
Estaba enfrentando el mismo problema al intentar truncar un VARCHAR de 32 a 8 y obtener el
ERROR: value too long for type character varying(8)
. Quiero mantenerme lo más cerca posible de SQL porque estoy usando una estructura similar a JPA hecha por nosotros mismos que podríamos tener que cambiar a diferentes DBMS de acuerdo con las elecciones del cliente (PostgreSQL es el predeterminado). Por lo tanto, no quiero usar el truco de alterar las tablas del sistema.Terminé usando la
USING
declaración enALTER TABLE
:Como señaló @raylu,
ALTER
adquiere un bloqueo exclusivo en la mesa para que todas las demás operaciones se retrasen hasta que se complete.fuente
ALTER
adquiere un bloqueo exclusivo en la mesa y evita todas las demás operacionesAgregar nueva columna y reemplazar una nueva por la anterior funcionó para mí, en redshift postgresql, consulte este enlace para obtener más detalles https://gist.github.com/mmasashi/7107430
fuente
Aquí está el caché de la página descrita por Greg Smith. En caso de que también muera, la declaración alter se ve así:
Cuando su tabla es TABLE1, la columna es COL1 y desea establecerla en 35 caracteres (el +4 es necesario para fines heredados de acuerdo con el enlace, posiblemente la sobrecarga a la que hace referencia AH en los comentarios).
fuente
Si coloca el alter en una transacción, la tabla no debe bloquearse:
Esto funcionó para mí increíblemente rápido, unos segundos en una mesa con más de 400k filas.
fuente
ALTER
instrucción? No lo hace.COMMIT
. El reiniciador solo tiene sentido si desea colocar más comandos en la misma transacción.He encontrado una manera muy fácil de cambiar el tamaño, es decir, la anotación @Size (min = 1, max = 50) que forma parte de "import javax.validation.constraints", es decir, "import javax.validation.constraints.Size;"
fuente
Intente ejecutar la siguiente tabla alter:
fuente