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?
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 mitn
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.
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.
Und mit "pure SQL" Benchmarks (ohne externes Skript)
verwenden Sie einen beliebigen string_generator mit UTF8
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.
Meine Ergebnisse nach dem Durchschnitt in vielen Maschinen und vielen Tests: egal
(statistisch weniger als Standardabweichung).
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%')
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
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.
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.
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.
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