Devrais-je ajouter une limite de longueur arbitraire aux colonnes VARCHAR?

35

Selon la documentation de PostgreSQL , il n'y a pas de différence de performance entre VARCHAR, VARCHAR(n)et TEXT.

Devrais-je ajouter une limite de longueur arbitraire à une colonne de nom ou d' adresse ?

Edit: Pas dupe de:

Je sais que le CHARtype est un vestige du passé et je suis intéressé non seulement par la performance, mais par d'autres avantages et inconvénients comme Erwin dans sa réponse étonnante.

Daniel Serodio
la source

Réponses:

45

La réponse est non .
N'ajoutez pas de modificateur de longueur varcharsi vous pouvez l'éviter. La plupart du temps, de toute façon, vous n'avez pas besoin d'une restriction de longueur. Il suffit d'utiliser textpour toutes les données de personnage. Faites cela varchar(pas de modificateur de longueur) si vous devez rester compatible avec les SGBDR qui n’en ont pas text.

La performance est presque la même - textest un peu plus rapide dans de rares situations , et vous enregistrez les cycles pour le contrôle de la longueur.

Si vous devez réellement imposer une longueur maximale, utilisez textquand même et ajoutez une contrainte de vérification pour cela:

ALTER TABLE tbl ADD CONSTRAINT tbl_col_len CHECK (length(col) < 51);

Vous pouvez modifier ou supprimer une telle contrainte à tout moment sans avoir à vous soucier de la définition de la table et de tous les objets qui en dépendent (vues, fonctions, clés étrangères, ...)

Avec les modificateurs de longueur, vous rencontrez simplement des problèmes comme celui - ci ou celui-ci ...

PostgreSQL 9.1 a introduit une nouvelle fonctionnalité pour alléger quelque peu la douleur. Je cite les notes de publication ici :

Permettre ALTER TABLE ... SET DATA TYPEd'éviter les réécritures de table dans les cas appropriés (Noah Misch, Robert Haas)

Par exemple, la conversion d'une varcharcolonne en texte ne nécessite plus une réécriture du tableau. Cependant, l'augmentation de la contrainte de longueur sur une varcharcolonne nécessite toujours une réécriture de table.

Erwin Brandstetter
la source
Je pense que cette réponse serait bien meilleure si elle était simplement "non, n'ajoutez jamais de limites arbitraires à une vraie base de données." Je pense qu’une grande partie de cette réponse nécessite des corrections et des informations complémentaires, mais elle est tout à fait hors sujet et pourrait détourner votre attention de votre conclusion avec laquelle je suis tout à fait d’accord.
Evan Carroll
Oui, toutes basées sur les versions de Postgres antérieures à 9.1 - 6 ans auparavant. Un peu poussiéreux maintenant, mais le conseil de base est toujours bon.
Erwin Brandstetter
Est-ce une bonne ou une mauvaise idée d'ajouter une contrainte de vérification pour chaque colonne de texte afin de vérifier l'intégrité et de s'assurer qu'un bogue dans le client n'utilise pas tout l'espace disque de la base de données en insérant un très grand texte?
Code
@ Code: C'est une option viable. Si vous avez plusieurs colonnes avec la même contrainte, considérez les domaines . Ou varchar(n)après tout, pour des raisons de simplicité - si les inconvénients ne vous concernent généralement pas. (La limite n'est pas arbitraire dans votre cas si vous souhaitez appliquer une longueur maximale réelle.)
Erwin Brandstetter le
12

Si vous voyez la limite de longueur comme une sorte de contrainte de vérification pour vous assurer de valider les données, alors oui, ajoutez-en une. En fait, vous voudrez peut-être ne pas utiliser une définition de longueur, mais une vraie contrainte de vérification, pour accélérer la modification de la limite.

Pour modifier (augmenter) une limite de longueur, vous devez exécuter une opération ALTER TABLEdont l’achèvement peut prendre un certain temps (en raison d’une possible réécriture de la table) au cours de laquelle un verrouillage exclusif de la table est nécessaire.

Modifier (c.-à-d. Supprimer et recréer) une contrainte de vérification est une opération très brève et nécessite uniquement la lecture des données de la table. Aucune ligne ne sera modifiée. Cela va donc être beaucoup plus rapide (ce qui signifie que le verrou exclusif de la table sera maintenu plus longtemps).

Pendant le fonctionnement, il n’ya aucune différence entre un text, une varcharou une varchar(5000)colonne.

un cheval sans nom
la source
par simple curiosité, pourquoi pensez-vous que cette vérification de la longueur ne peut pas être effectuée sur une application client lors de la capture de données?
PirateApp
4
@PirateApp: car très souvent, il y aura plus d'une application ou une source de données externe (pensez aux importations par lots nocturnes). Et presque toujours, la base de données (et les données) vivent plus longtemps qu'une application.
a_horse_with_no_name
2

La question est précisément de savoir si l' ajout d'une limite de longueur arbitraire aux colonnes VARCHAR?

Pour cela, la réponse est simplement "non". Il n'y a rien qui puisse justifier l'ajout d'une limite arbitraire, comme dans les bases de données inférieures qui prennent en charge varchar(max)ou utilisent des conventions telles que varchar(255). Cependant, si la spécification aborde une limite, je pense que la réponse devient beaucoup plus complexe, en particulier sur les versions modernes de PostgreSQL. Et, pour cela, je me pencherais vers OUI .

À mon avis, la limite est un choix judicieux si la spécification l'exige. Surtout pour des charges de travail plus raisonnables. Si pour aucune autre raison, préserver les métadonnées.

De ma réponse ici, indexer les performances de CHAR vs VARCHAR (Postgres) , où je traite de la valeur des méta-données.

Si je trouvais une spécification qui avait des clés de texte de longueur variable qui étaient significatives et que j'avais confiance d'avoir une longueur maximale constante, je l'utilisais varcharaussi. Cependant, je ne vois rien qui réponde à ces critères.

Evan Carroll
la source
1

Il semble y avoir une différence de performances si vous VARCHARutilisez régulièrement des chaînes très volumineuses, car "les chaînes longues sont compressées automatiquement par le système" et "les valeurs très longues sont également stockées dans des tables en arrière-plan". Théoriquement, cela signifierait qu'un volume élevé de demandes pour un très long champ de chaîne serait plus lent que pour un court champ de chaîne. Vous ne rencontrerez probablement jamais ce problème, car les noms et les adresses ne seront pas très longs.

Toutefois, en fonction de votre utilisation de ces chaînes en dehors de votre base de données, vous souhaiterez peut-être ajouter une limite pratique pour éviter toute utilisation abusive du système. Par exemple, si vous affichez le nom et l'adresse d'un formulaire quelque part, vous ne pourrez peut-être pas afficher un paragraphe entier de texte dans le champ "nom". Il serait donc judicieux de limiter la colonne du nom à quelque chose comme 500 personnages.

Edward
la source
1
Autant que je sache, il n’y a aucune différence entre les champs TOASTing varchar et text.
dezso
VARCHARest un sucre purement syntaxique car TEXTdans Postgres, il n’ya pas de différence de traitement; Le stockage de compression / arrière-plan que vous mentionnez est effectué en fonction de la longueur réelle des données dans la colonne et non des métadonnées de la colonne. Les colonnes TEXT sont stockées en interne sous la forme d'une varlenastructure C (qui est un tableau de longueur variable avec les 4 premiers octets stockant la longueur lors de la création / mise à jour) et c'est cette structure qui est optimisée en fonction de sa longueur.
cowbert