web-dev-qa-db-fra.com

PostgreSQL: Différence entre text et varchar (caractère variable)

Quelle est la différence entre le type de données text et les types de données character varying (varchar)?

Selon la documentation

Si la variable character est utilisée sans spécificateur de longueur, le type accepte les chaînes de toutes tailles. Ce dernier est une extension PostgreSQL.

et

De plus, PostgreSQL fournit le type de texte, qui stocke des chaînes de n'importe quelle longueur. Bien que le type de texte ne soit pas dans la norme SQL, plusieurs autres systèmes de gestion de base de données SQL l'ont également.

Alors quelle est la différence?

538
Adam Matan

Il n'y a pas de différence, sous le capot, tout est varlena ( tableau de longueur variable ).

Consultez cet article de Depesz: http://www.depesz.com/index.php/2010/03/02/charx-vs-varcharx-vs-varchar-vs-text/

Quelques faits saillants:

Pour tout résumer:

  • char (n) - prend trop d'espace lorsqu'il s'agit de valeurs inférieures à n (les compresse sur n), et peut entraîner des erreurs subtiles en raison de l'ajout d'espaces de fin. En outre, il est problématique de modifier le limite
  • varchar (n) - il est problématique de changer la limite dans un environnement réel (nécessite un verrou exclusif lors de la modification d'un tableau)
  • varchar - juste comme le texte
  • text - pour moi un gagnant - sur (n) types de données car il ne leur manque aucun problème, et sur varchar - car son nom est distinct

L'article effectue des tests détaillés pour montrer que les performances des insertions et des sélections pour les 4 types de données sont similaires. Il examine également en détail d'autres moyens de limiter la longueur lorsque cela est nécessaire. Les contraintes ou domaines basés sur les fonctions offrent l'avantage d'augmenter instantanément la contrainte de longueur, et comme il est rare de diminuer une contrainte de longueur de chaîne, depesz conclut que l'un d'eux est généralement le meilleur choix pour une limite de longueur.

646
Frank Heikens

Comme l'indique " Types de caractères " dans la documentation, varchar(n), char(n) et text sont tous stockés de la même manière. La seule différence est que des cycles supplémentaires sont nécessaires pour vérifier la longueur, le cas échéant, ainsi que l'espace et le temps supplémentaires nécessaires si un remplissage est nécessaire pour char(n).

Toutefois, lorsque vous n'avez besoin de stocker qu'un seul caractère, l'utilisation du type spécial "char" présente un léger avantage en termes de performances (conservez les guillemets, ils font partie du nom du type). Vous obtenez un accès plus rapide au terrain et il n'y a pas de surcharge pour stocker la longueur.

Je viens de faire un tableau de 1 000 000 de "char" aléatoires choisis dans l'alphabet des minuscules. Une requête pour obtenir une distribution de fréquence (select count(*), field ... group by field) prend environ 650 millisecondes, contre environ 760 sur les mêmes données à l'aide d'un champ text.

104
George

MISE À JOUR DES RÉFÉRENCES POUR 2016 (pg9.5 +)

Et en utilisant des tests "pur SQL" (sans script externe)

  1. utiliser n'importe quel string_generator avec UTF8

  2. principaux repères:

    2.1. INSÉRER

    2.2. SELECT comparer et compter


CREATE FUNCTION string_generator(int DEFAULT 20,int DEFAULT 10) RETURNS text AS $f$
  SELECT array_to_string( array_agg(
    substring(md5(random()::text),1,$1)||chr( 9824 + (random()*10)::int )
  ), ' ' ) as s
  FROM generate_series(1, $2) i(x);
$f$ LANGUAGE SQL IMMUTABLE;

Préparer un test spécifique (exemples)

DROP TABLE IF EXISTS test;
-- CREATE TABLE test ( f varchar(500));
-- CREATE TABLE test ( f text); 
CREATE TABLE test ( f text  CHECK(char_length(f)<=500) );

Effectuer un test de base:

INSERT INTO test  
   SELECT string_generator(20+(random()*(i%11))::int)
   FROM generate_series(1, 99000) t(i);

Et d'autres tests,

CREATE INDEX q on test (f);

SELECT count(*) FROM (
  SELECT substring(f,1,1) || f FROM test WHERE f<'a0' ORDER BY 1 LIMIT 80000
) t;

... Et utilisez EXPLAIN ANALYZE.

MISE À JOUR À NOUVEAU 2018 (pg10)

petite édition pour ajouter les résultats de 2018 et renforcer les recommandations.


Résultats en 2016 et 2018

Mes résultats, après la moyenne, sur de nombreuses machines et de nombreux tests: tous les mêmes
(statistiquement moins l'écart type).

Recommandation

  • Utilisez le type de données text,
    évitez les anciennes varchar(x) car, parfois, ce n'est pas un standard, par ex. dans CREATE FUNCTION clauses varchar(x)varchar(y).

  • exprimer des limites (avec la même varchar performance!) par avec la clause CHECK dans le CREATE TABLE
    par exemple. CHECK(char_length(x)<=10).
    Avec une perte de performance négligeable dans INSERT/UPDATE, vous pouvez également contrôler les plages et la structure des chaînes.
    par exemple. CHECK(char_length(x)>5 AND char_length(x)<=20 AND x LIKE 'Hello%')

45
Peter Krauss

Sur le manuel PostgreSQL

Il n'y a pas de différence de performances entre ces trois types, mis à part un espace de stockage accru lorsque vous utilisez le type complété par des blancs et quelques cycles d'UC supplémentaires pour vérifier la longueur lors du stockage dans une colonne de longueur limitée. Alors que character (n) présente des avantages en termes de performances sur d’autres systèmes de base de données, il n’existe aucun avantage de ce type dans PostgreSQL; En fait, le caractère (n) est généralement le plus lent des trois en raison de ses coûts de stockage supplémentaires. Dans la plupart des cas, il est préférable d'utiliser du texte ou des caractères différents.

J'utilise habituellement du texte

Références: http://www.postgresql.org/docs/current/static/datatype-character.html

30
user5507680

À mon avis, varchar(n) a ses propres avantages. Oui, ils utilisent tous le même type sous-jacent et tout ça. Cependant, il convient de souligner que la taille maximale des index dans PostgreSQL est de 2712 octets par ligne.

TL; DR: Si vous utilisez text tapez sans contrainte et possédez des index sur ces colonnes, il est Il est fort possible que vous atteigniez cette limite pour certaines de vos colonnes et que vous obteniez une erreur lorsque vous essayez d’insérer des données, mais avec varchar(n), vous pouvez l’empêcher.

Quelques détails supplémentaires: Le problème ici est que PostgreSQL ne donne aucune exception lors de la création d'index pour text type ou varchar(n)n est supérieur à 2712. Cependant, cela produira une erreur lorsqu’on essaiera d’insérer un enregistrement dont la taille compressée est supérieure à 2712. Cela signifie que vous pouvez insérer facilement une chaîne de 100 000 caractères composée de caractères répétitifs, car elle sera comprimée bien en dessous de 2712 mais vous ne pourrez peut-être pas insérer une chaîne de 4 000 caractères car la taille compressée est supérieure à 2712 octets. En utilisant varchar(n)n n'est pas trop supérieur à 2712, vous êtes à l'abri de ces erreurs.

15
sotn

text et varchar ont des conversions de types implicites différentes. Le plus gros impact que j'ai remarqué est la gestion des espaces de fuite. Par exemple ...

select ' '::char = ' '::varchar, ' '::char = ' '::text, ' '::varchar = ' '::text

renvoie true, false, true et non pas true, true, true comme on pourrait s'y attendre.

14
bpd

Un peu OT: Si vous utilisez Rails, le formatage standard des pages Web peut être différent. Pour les formulaires de saisie de données, les zones text sont déplaçables, mais les zones character varying (Rails string) sont d'une ligne. Afficher les vues sont aussi longues que nécessaire.

4
Greg

character varying(n), varchar(n)les deux identiques). la valeur sera tronquée à n caractères sans générer d'erreur.

character(n), char(n) - (les deux identiques). longueur fixe et tampon avec des flans jusqu'à la fin de la longueur.

text - Longueur illimitée.

--- (Exemple:

Table test:
   a character(7)
   b varchar(7)

insert "ok    " to a
insert "ok    " to b

Nous obtenons les résultats:

a        | (a)char_length | b     | (b)char_length
----------+----------------+-------+----------------
"ok     "| 7              | "ok"  | 2
0
ofir_aghai