it-swarm.com.de

PostgreSQL: Unterschied zwischen Text und Varchar (Zeichen variieren)

Was ist der Unterschied zwischen dem Datentyp text und dem Datentyp character varying (varchar)?

Nach die Dokumentation

Wenn Zeichenvariation ohne Längenangabe verwendet wird, akzeptiert der Typ Zeichenfolgen beliebiger Größe. Letzteres ist eine PostgreSQL-Erweiterung.

und

Zusätzlich bietet PostgreSQL den Texttyp, in dem Zeichenfolgen beliebiger Länge gespeichert werden. Obwohl der Typ text nicht im SQL-Standard enthalten ist, verfügt er auch über einige andere SQL-Datenbankverwaltungssysteme.

Was ist der Unterschied?

538
Adam Matan

Es gibt keinen Unterschied, unter der Haube ist alles varlena ( Array mit variabler Länge ).

Überprüfen Sie diesen Artikel von Depesz: http://www.depesz.com/index.php/2010/03/02/charx-vs-varcharx-vs-varchar-vs-text/

Ein paar Höhepunkte:

Um es zusammenzufassen:

  • char (n) - nimmt zu viel Platz in Anspruch, wenn es sich um Werte handelt, die kürzer als n sind (füllt sie mit n auf), und kann aufgrund des Hinzufügens von nachgestellten Leerzeichen zu subtilen Fehlern führen, und es ist problematisch, das zu ändern Grenze
  • varchar (n) - es ist problematisch, das Limit in der Live-Umgebung zu ändern (erfordert exklusive Sperre beim Ändern der Tabelle)
  • varchar - genau wie text
  • Text - für mich ein Gewinner - über (n) Datentypen, weil es keine Probleme gibt, und über varchar - weil es einen eindeutigen Namen hat

Der Artikel führt ausführliche Tests durch, um zu zeigen, dass die Leistung von Einfügungen und Auswahlen für alle 4 Datentypen ähnlich ist. Es werden auch alternative Möglichkeiten zur Begrenzung der Länge bei Bedarf detailliert beschrieben. Funktionsbasierte Einschränkungen oder Domänen bieten den Vorteil einer sofortigen Erhöhung der Längenbeschränkung. Auf der Grundlage, dass die Verringerung einer Zeichenfolgenlängenbeschränkung selten ist, kommt depesz zu dem Schluss, dass eine davon normalerweise die beste Wahl für eine Längenbeschränkung ist.

646
Frank Heikens

Wie in der Dokumentation unter " Character Types " angegeben, werden varchar(n), char(n) und text alle auf dieselbe Weise gespeichert. Der einzige Unterschied besteht darin, dass zusätzliche Zyklen erforderlich sind, um die Länge zu überprüfen, sofern eine angegeben ist, sowie den zusätzlichen Platz und die Zeit, die erforderlich sind, wenn für char(n) ein Auffüllen erforderlich ist.

Wenn Sie jedoch nur ein einzelnes Zeichen speichern müssen, bietet die Verwendung des Sondertyps "char" einen leichten Leistungsvorteil (doppelte Anführungszeichen - sie sind Teil des Typnamens). Sie erhalten einen schnelleren Zugriff auf das Feld und es gibt keinen Overhead zum Speichern der Länge.

Ich habe gerade eine Tabelle mit 1.000.000 zufälligen "char" erstellt, die aus dem Kleinbuchstaben ausgewählt wurde. Eine Abfrage zum Abrufen einer Häufigkeitsverteilung (select count(*), field ... group by field) dauert ungefähr 650 Millisekunden gegenüber ungefähr 760 für dieselben Daten, wenn ein text -Feld verwendet wird.

104
George

AKTUALISIERUNG DER MARKEN FÜR 2016 (S.9.5 +)

Und mit "pure SQL" Benchmarks (ohne externes Skript)

  1. verwenden Sie einen beliebigen string_generator mit UTF8

  2. hauptbenchmarks:

    2.1. EINFÜGEN

    2.2. SELECT vergleichen und zählen


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;

Spezifischen Test vorbereiten (Beispiele)

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) );

Führen Sie einen Basistest durch:

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

Und andere 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;

... und benutze EXPLAIN ANALYZE.

WIEDER AKTUALISIERT 2018 (S. 10)

little edit fügt die Ergebnisse von 2018 hinzu und verstärkt die Empfehlungen.


Ergebnisse in 2016 und 2018

Meine Ergebnisse nach dem Durchschnitt in vielen Maschinen und vielen Tests: egal
(statistisch weniger als Standardabweichung).

Empfehlung

  • Verwenden Sie den Datentyp text,
    Vermeiden Sie alte varchar(x), da dies manchmal kein Standard ist, z. in CREATE FUNCTION -Klauseln varchar(x)varchar(y).

  • grenzen (bei gleicher varchar Leistung!) durch die CHECK Klausel im CREATE TABLE ausdrücken
    z.B. CHECK(char_length(x)<=10).
    Mit einem vernachlässigbaren Leistungsverlust in INSERT/UPDATE können Sie auch Bereiche und String-Struktur steuern
    z.B. CHECK(char_length(x)>5 AND char_length(x)<=20 AND x LIKE 'Hello%')

45
Peter Krauss

Auf PostgreSQL Handbuch

Es gibt keinen Leistungsunterschied zwischen diesen drei Typen, abgesehen von erhöhtem Speicherplatz bei Verwendung des leergefüllten Typs und ein paar zusätzlichen CPU-Zyklen zum Überprüfen der Länge beim Speichern in einer Spalte mit begrenzter Länge. Während Zeichen (n) in einigen anderen Datenbanksystemen Leistungsvorteile bietet, gibt es in PostgreSQL keinen solchen Vorteil. Tatsächlich ist das Zeichen (n) aufgrund der zusätzlichen Speicherkosten normalerweise das langsamste der drei Zeichen. In den meisten Situationen sollten stattdessen unterschiedliche Texte oder Zeichen verwendet werden.

Normalerweise benutze ich Text

Referenzen: http://www.postgresql.org/docs/current/static/datatype-character.html

30
user5507680

Meiner Meinung nach hat varchar(n) seine eigenen Vorteile. Ja, sie verwenden alle den gleichen zugrunde liegenden Typ und das alles. Es sollte jedoch darauf hingewiesen werden, dass Indizes in PostgreSQL eine Größenbeschränkung von 2712 Bytes pro Zeile haben.

TL; DR: Wenn Sie den text -Typ ohne Einschränkung verwenden und Indizes für diese Spalten haben, ist dies der Fall Es ist sehr wahrscheinlich, dass Sie diese Grenze für einige Ihrer Spalten überschreiten und eine Fehlermeldung erhalten, wenn Sie versuchen, Daten einzufügen. Mit varchar(n) können Sie dies jedoch verhindern.

Weitere Details: Das Problem hierbei ist, dass PostgreSQL beim Erstellen von Indizes für den text -Typ oder varchar(n) keine Ausnahmen macht, wobei n größer als 2712 ist. Es wird jedoch ein Fehler ausgegeben, wenn versucht wird, einen Datensatz mit einer komprimierten Größe von mehr als 2712 einzufügen. Dies bedeutet, dass Sie problemlos 100.000 Zeichen einer Zeichenfolge einfügen können, die sich aus sich wiederholenden Zeichen zusammensetzt, da sie weit unter 2712 komprimiert wird. Möglicherweise können Sie jedoch keine Zeichenfolgen mit 4000 Zeichen einfügen, da die komprimierte Größe größer als 2712 Byte ist. Wenn Sie varchar(n) verwenden, wobei n nicht zu viel größer als 2712 ist, sind Sie vor diesen Fehlern sicher.

15
sotn

text und varchar haben unterschiedliche implizite Typkonvertierungen. Die größte Auswirkung, die mir aufgefallen ist, ist der Umgang mit nachgestellten Leerzeichen. Beispielsweise ...

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

gibt true, false, true und nicht true, true, true zurück, wie Sie es vielleicht erwarten.

14
bpd

Etwas OT: Wenn Sie Rails verwenden, kann die Standardformatierung von Webseiten unterschiedlich sein. Bei Dateneingabeformularen können die Felder text gescrollt werden, die Felder character varying (Rails string) sind jedoch einzeilig. Showansichten sind so lange wie nötig.

4
Greg

character varying(n), varchar(n)Beide gleich). value wird auf n Zeichen gekürzt, ohne einen Fehler auszulösen.

character(n), char(n) - (Beide gleich). feste Länge und wird mit Leerzeichen bis zum Ende der Länge auffüllen.

text - Unbegrenzte Länge.

--- (Beispiel:

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

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

Wir erhalten die Ergebnisse:

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