J'ai une question sur la ALTER TABLE
commande sur une très grande table (près de 30 millions de lignes). L'une de ses colonnes est a varchar(255)
et je voudrais la redimensionner en un varchar(40)
. En gros, je voudrais changer ma colonne en exécutant la commande suivante:
ALTER TABLE mytable ALTER COLUMN mycolumn TYPE varchar(40);
Je n'ai aucun problème si le processus est très long mais il semble que ma table ne soit plus lisible pendant la commande ALTER TABLE. Y a-t-il un moyen plus intelligent? Peut-être ajouter une nouvelle colonne, copier les valeurs de l'ancienne colonne, supprimer l'ancienne colonne et enfin renommer la nouvelle?
Tout indice sera grandement apprécié! Merci d'avance,
Remarque: j'utilise PostgreSQL 9.0.
postgresql
varchar
alter-table
Labynocle
la source
la source
resizing
ne rendra pas la table moins encombrante?varchar(255)
à PostgreSQL, il n'allouera pas 255 octets pour une valeur dont la longueur réelle est de 40 octets. Il allouera 40 octets (plus une surcharge interne). La seule chose quibe changed by the
ALTER TABLE` est le nombre maximum d'octets que vous pouvez stocker dans cette colonne sans obtenir une erreur de PG.Réponses:
Il y a une description de la façon de faire cela à Redimensionner une colonne dans une table PostgreSQL sans changer de données . Vous devez pirater les données du catalogue de la base de données. La seule façon de le faire officiellement est avec ALTER TABLE, et comme vous l'avez noté, ce changement verrouille et réécrit la table entière pendant son exécution.
Assurez-vous de lire la section Types de caractères de la documentation avant de modifier cela. Toutes sortes de cas étranges à connaître ici. Le contrôle de longueur est effectué lorsque les valeurs sont stockées dans les lignes. Si vous piratez une limite inférieure, cela ne réduira pas du tout la taille des valeurs existantes. Vous seriez sage de faire un scan sur toute la table à la recherche de lignes dont la longueur du champ est> 40 caractères après avoir effectué la modification. Vous devrez trouver comment tronquer ceux-ci manuellement - vous êtes donc revenu sur certains verrous uniquement sur des verrous surdimensionnés - parce que si quelqu'un essaie de mettre à jour quoi que ce soit sur cette ligne, il le rejettera comme trop gros maintenant, au point il va stocker la nouvelle version de la ligne. La hilarité s'ensuit pour l'utilisateur.
VARCHAR est un type terrible qui n'existe dans PostgreSQL que pour se conformer à sa terrible partie associée du standard SQL. Si vous ne vous souciez pas de la compatibilité multi-bases de données, envisagez de stocker vos données sous forme de TEXTE et ajoutez une contrainte pour limiter sa longueur. Les contraintes que vous pouvez modifier sans ce problème de verrouillage / réécriture de table, et elles peuvent faire plus de vérification d'intégrité que simplement la vérification de longueur faible.
la source
Dans PostgreSQL 9.1, il existe un moyen plus simple
http://www.postgresql.org/message-id/[email protected]
la source
Ok, je suis probablement en retard à la fête, MAIS ...
IL N'Y A PAS BESOIN DE REDIMENSIONNER LA COLONNE DANS VOTRE CAS!
Postgres, contrairement à certaines autres bases de données, est assez intelligent pour n'utiliser que juste assez d'espace pour tenir la chaîne (même en utilisant la compression pour les chaînes plus longues), donc même si votre colonne est déclarée comme VARCHAR (255) - si vous stockez des chaînes de 40 caractères dans la colonne, l'utilisation de l'espace sera de 40 octets + 1 octet de surcharge.
( http://www.postgresql.org/docs/9.0/interactive/datatype-character.html )
La spécification de taille dans VARCHAR est uniquement utilisée pour vérifier la taille des valeurs insérées, elle n'affecte pas la disposition du disque. En fait, les champs VARCHAR et TEXT sont stockés de la même manière dans Postgres .
la source
J'étais confronté au même problème en essayant de tronquer un VARCHAR de 32 à 8 et d'obtenir le fichier
ERROR: value too long for type character varying(8)
. Je veux rester aussi proche de SQL que possible car j'utilise une structure de type JPA que nous pourrions avoir à passer à différents SGBD en fonction des choix du client (PostgreSQL étant celui par défaut). Par conséquent, je ne veux pas utiliser l'astuce de modifier les tables système.J'ai fini d'utiliser la
USING
déclaration dans leALTER TABLE
:Comme @raylu l'a noté,
ALTER
acquiert un verrou exclusif sur la table afin que toutes les autres opérations soient retardées jusqu'à ce qu'elle se termine.la source
ALTER
acquiert un verrou exclusif sur la table et empêche toutes les autres opérationsL'ajout d'une nouvelle colonne et le remplacement de la nouvelle par l'ancienne a fonctionné pour moi, sur redshift postgresql, reportez-vous à ce lien pour plus de détails https://gist.github.com/mmasashi/7107430
la source
Voici le cache de la page décrite par Greg Smith. Dans le cas où cela meurt également, l'instruction alter ressemble à ceci:
Lorsque votre table est TABLE1, la colonne est COL1 et vous voulez la définir sur 35 caractères (le +4 est nécessaire à des fins d'héritage selon le lien, éventuellement la surcharge mentionnée par AH dans les commentaires).
la source
si vous mettez l'altérer dans une transaction, la table ne doit pas être verrouillée:
cela a fonctionné pour moi très rapidement, quelques secondes sur une table avec plus de 400 000 lignes.
la source
ALTER
instruction? Ce n'est pas le cas.COMMIT
. Le wrapper n'a de sens que si vous souhaitez placer plus de commandes dans la même transaction.J'ai trouvé un moyen très simple de changer la taille à savoir l'annotation @Size (min = 1, max = 50) qui fait partie de "import javax.validation.constraints" ie "import javax.validation.constraints.Size;"
la source
Essayez d'exécuter l'alter table suivante:
la source