Best Practices für die Länge der SQL-Varchar-Spalte [geschlossen]

288

Jedes Mal, wenn eine neue SQL-Tabelle eingerichtet oder eine neue varcharSpalte zu einer vorhandenen Tabelle hinzugefügt wird , frage ich mich eines: Was ist der beste Wert für dielength .

Angenommen, Sie haben eine Spalte mit dem Namen nametype varchar. Sie müssen also die Länge auswählen. Ich kann mir keinen Namen> 20 Zeichen vorstellen, aber Sie werden es nie erfahren. Aber anstatt 20 zu verwenden, runde ich immer auf die nächste 2 ^ n-Zahl auf. In diesem Fall würde ich 32 als Länge wählen. Ich mache das, weil aus Sicht der Informatiker eine Zahl 2 ^ n mehr aussiehteven für mich als andere Zahlen, und ich gehe nur davon aus, dass die Architektur darunter diese Zahlen etwas besser verarbeiten kann als andere.

Auf der anderen Seite setzt der MSSQL-Server beispielsweise den Standardlängenwert auf 50, wenn Sie eine Varchar-Spalte erstellen. Das bringt mich zum Nachdenken. Warum 50? Ist es nur eine Zufallszahl oder basiert sie auf der durchschnittlichen Spaltenlänge oder was?

Es könnte auch sein - oder ist es wahrscheinlich auch -, dass verschiedene SQL Server-Implementierungen (wie MySQL, MSSQL, Postgres, ...) unterschiedliche Werte für die beste Spaltenlänge haben.

esskar
quelle

Antworten:

238

Kein mir bekanntes DBMS hat eine "Optimierung", die eine Leistung VARCHARmit einer 2^nLänge besser macht als eine mit einer maxLänge, die keine Potenz von 2 ist.

Ich denke, frühe SQL Server-Versionen haben a VARCHARmit einer Länge von 255 anders behandelt als eine mit einer höheren maximalen Länge. Ich weiß nicht, ob dies noch der Fall ist.

Bei fast allen DBMS wird der tatsächlich erforderliche Speicher nur durch die Anzahl der eingegebenen Zeichen bestimmt, nicht durch die von maxIhnen definierte Länge. Aus Speichersicht (und höchstwahrscheinlich auch unter Leistungsgesichtspunkten) spielt es also keine Rolle, ob Sie eine Spalte als VARCHAR(100)oder deklarieren VARCHAR(500).

Sie sollten die maxfür eine VARCHARSpalte angegebene Länge als eine Art Einschränkung (oder Geschäftsregel) und nicht als eine technische / physische Sache betrachten.

Für PostgreSQL ist das beste Setup die Verwendung textohne Längenbeschränkung und aCHECK CONSTRAINT die Anzahl der Zeichen auf die Anforderungen Ihres Unternehmens zu beschränken.

Wenn sich diese Anforderung ändert, ist das Ändern der Prüfbedingung viel schneller als das Ändern der Tabelle (da die Tabelle nicht neu geschrieben werden muss).

Dasselbe kann für Oracle und andere angewendet werden - in Oracle wäre dies jedoch VARCHAR(4000)nicht der Fall text.

Ich weiß nicht, ob es einen physischen Speicherunterschied zwischen VARCHAR(max)und z VARCHAR(500). B. in SQL Server gibt. Aber anscheinend gibt es einen Leistungseinbruch bei der Verwendung varchar(max)im Vergleich zu varchar(8000).

Siehe diesen Link (gepostet von Erwin Brandstetter als Kommentar)

Bearbeiten 2013-09-22

In Bezug auf Bigowns Kommentar:

In Postgres - Versionen vor 9.2 (das war nicht verfügbar , als ich die erste Antwort schrieb) eine Änderung der Spaltendefinition hat die gesamte Tabelle neu zu schreiben, siehe zB hier . Seit 9.2 ist dies nicht mehr der Fall und ein schneller Test bestätigte, dass das Erhöhen der Spaltengröße für eine Tabelle mit 1,2 Millionen Zeilen tatsächlich nur 0,5 Sekunden dauerte.

Für Oracle scheint dies auch zuzutreffen, gemessen an der Zeit, die zum Ändern der varcharSpalte einer großen Tabelle benötigt wird. Aber ich konnte keine Referenz dafür finden.

Für MySQL heißt es im Handbuch " In den meisten Fällen ALTER TABLEwird eine temporäre Kopie der Originaltabelle erstellt ". Und meine eigenen Tests bestätigen Folgendes: Das Ausführen einer ALTER TABLETabelle mit 1,2 Millionen Zeilen (wie in meinem Test mit Postgres) zum Erhöhen der Größe einer Spalte dauerte 1,5 Minuten. In MySQL können Sie jedoch nicht die "Problemumgehung" verwenden, um eine Prüfbedingung zu verwenden, um die Anzahl der Zeichen in einer Spalte zu begrenzen.

Für SQL Server konnte ich keine eindeutige Aussage dazu finden, aber die Ausführungszeit zum Erhöhen der Größe einer varcharSpalte (wieder die Tabelle mit 1,2 Millionen Zeilen von oben) zeigt an, dass kein Umschreiben stattfindet.

Bearbeiten 2017-01-24

Scheint, als hätte ich mich (zumindest teilweise) in Bezug auf SQL Server geirrt. Siehe diese Antwort von Aaron Bertrand , die zeigt, dass die deklarierte Länge von a nvarcharoder varcharSpalten einen großen Unterschied für die Leistung macht.

ein Pferd ohne Name
quelle
34
Tatsächlich gibt es einen Unterschied zwischen VARCHAR (255) und VARCHAR (500), selbst wenn Sie 1 Zeichen in eine solche Spalte einfügen. Der am Ende der Zeile angehängte Wert ist eine Ganzzahl, in der die tatsächliche Länge der gespeicherten Daten gespeichert wird. Im Fall von VARCHAR (255) ist es eine 1-Byte-Ganzzahl. Im Fall von VARCHAR (500) sind es 2 Bytes. Es ist ein kleiner Unterschied, aber man sollte sich dessen bewusst sein. Ich habe keine Daten zur Verfügung, die sich auf die Leistung auswirken können, aber ich gehe davon aus, dass sie so klein sind, dass es sich nicht lohnt, sie zu untersuchen.
NB
1
@NB: Darauf habe ich mich für den "magischen" 255-Wert von SQL Server bezogen. Danke für die Klarstellung.
a_horse_with_no_name
4
@NB Auf welches RDBMS beziehen Sie sich? SQL Server? Dies wirkt sich auf die Leistung aus. [N] VARCHAR (max) arbeitet etwas langsamer als [N] VARCHAR (n). Ich wurde kürzlich auf diese Seite verwiesen . Das Gleiche gilt nicht für PostgreSQL, soweit ich weiß.
Erwin Brandstetter
@ErwinBrandstetter: Danke für den Link. Sieht aus wie varchar(max)ist wahrscheinlich eher wie OracleCLOB
a_horse_with_no_name
1
Durch Ändern der Varchar-Länge wird die Tabelle nicht neu geschrieben. Es wird lediglich die Einschränkungslänge für die gesamte Tabelle genau als CHECK CONSTRAINT überprüft. Wenn Sie die Länge erhöhen, gibt es nichts zu tun. Nur das nächste Einfügen oder Aktualisieren akzeptiert eine größere Länge. Wenn Sie die Länge verringern und alle Zeilen die neue kleinere Einschränkung erfüllen, ergreift Pg keine weiteren Maßnahmen, damit die nächsten Einfügungen oder Aktualisierungen nur die neue Länge schreiben können.
Maniero
69

VARCHAR(255)und VARCHAR(2)nehmen Sie genau die gleiche Menge Speicherplatz auf der Festplatte! Der einzige Grund, dies einzuschränken, besteht darin, dass Sie ein spezifisches Bedürfnis haben, es kleiner zu machen. Ansonsten machen sie alle 255.

Insbesondere beim Sortieren nehmen größere Spalten mehr Platz ein. Wenn dies die Leistung beeinträchtigt, müssen Sie sich darum kümmern und sie verkleinern. Wenn Sie jedoch immer nur eine Zeile aus dieser Tabelle auswählen, können Sie sie alle auf 255 setzen, und das spielt keine Rolle.

Siehe: Was sind die optimalen Varchar-Größen für MySQL?

Ariel
quelle
7
Warum nicht alle machen VARCHAR(MAX)? Speicherplatz ist nicht die einzige Überlegung bei der Modellierung einer Datenbank. Die Domäne, die Sie modellieren, sollte die Datentypen und die Größen bestimmen.
Oded
6
@Oded VARCHAR(MAX)ist nicht dasselbe wie varchar(255)oder varchar(65535)- varchar max ist ein textDatentyp. Und zu Ihrem Punkt - wenn er wüsste, welche "Domäne er modellierte", würde er diese Frage nicht stellen. Offensichtlich weiß er nicht, wie groß seine Daten werden, und ich versichere ihm, dass es nichts schadet, wenn er in voller Größe erstellt wird.
Ariel
4
@Ariel: Es gibt auch Probleme und Einschränkungen bei Indizes, die berücksichtigt werden müssen. Sie können keinen (a,b,c,d)Index haben, wenn alle vier Spalten vorhanden sind VARCHAR(255).
Ypercubeᵀᴹ
@ypercube Das stimmt, wenn Ihre Spalten einen Index benötigen, müssen Sie mit den Größen vorsichtiger sein. Die meisten Spalten benötigen jedoch keinen Index, sodass Sie sich die meiste Zeit keine Sorgen machen müssen.
Ariel
Ich denke, wenn wir den genauen Wert kennen, bevorzuge ich char. In der Zwischenzeit, wenn es immer noch vorhersehbar ist, verwende ich varchar und behalte 255, da es sich um eine dynamische Speicherzuweisung handelt, damit Sie sich keine Sorgen über die Größe machen, die verwendet wird
Faris Rayhan
54

Immer wenn ich eine neue SQL-Tabelle einrichte, sehe ich 2 ^ n als "gleichmäßiger" ... aber um die Antworten hier zusammenzufassen, gibt es keine signifikanten Auswirkungen auf den Speicherplatz, wenn Sie einfach varchar (2 ^ n) definieren. oder sogar varchar (MAX).

Sie sollten jedoch die möglichen Auswirkungen auf Speicher und Leistung vorhersehen, wenn Sie ein hohes varchar () -Limit festlegen. Angenommen, Sie erstellen eine Varchar-Spalte (MAX) für Produktbeschreibungen mit Volltextindizierung. Wenn 99% der Beschreibungen nur 500 Zeichen lang sind und Sie plötzlich jemanden finden, der diese Beschreibungen durch Wikipedia-Artikel ersetzt, werden Sie möglicherweise unerwartete signifikante Speicher- und Leistungstreffer feststellen.

Eine andere Sache, die von Bill Karwin zu beachten ist :

Es gibt eine mögliche Auswirkung auf die Leistung: In MySQL speichern temporäre Tabellen und MEMORY-Tabellen eine VARCHAR-Spalte als Spalte fester Länge, die auf ihre maximale Länge aufgefüllt ist. Wenn Sie VARCHAR-Spalten entwerfen, die viel größer sind als die größte Größe, die Sie benötigen, verbrauchen Sie mehr Speicher als nötig. Dies wirkt sich auf die Cache-Effizienz, die Sortiergeschwindigkeit usw. aus.

Überlegen Sie sich im Grunde nur vernünftige geschäftliche Einschränkungen und Fehler bei einer etwas größeren Größe. Wie @onedaywhen hervorhob, liegen Familiennamen in Großbritannien normalerweise zwischen 1 und 35 Zeichen. Wenn Sie sich für varchar (64) entscheiden, werden Sie nichts wirklich verletzen ... es sei denn, Sie speichern den Familiennamen dieses Mannes , der bis zu 666 Zeichen lang sein soll. In diesem Fall ist varchar (1028) vielleicht sinnvoller.

Und falls es hilfreich ist, hier ist, wie varchar 2 ^ 5 bis 2 ^ 10 aussehen könnte, wenn es gefüllt ist:

varchar(32)     Lorem ipsum dolor sit amet amet.

varchar(64)     Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie

varchar(128)    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie
                vestibulum massa. Nullam dignissim elementum molestie. Vehiculas

varchar(256)    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie
                vestibulum massa. Nullam dignissim elementum molestie. Vehiculas
                velit metus, sit amet tristique purus condimentum eleifend. Quis
                que mollis magna vel massa malesuada bibendum. Proinde tincidunt

varchar(512)    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie
                vestibulum massa. Nullam dignissim elementum molestie. Vehiculas
                velit metus, sit amet tristique purus condimentum eleifend. Quis
                que mollis magna vel massa malesuada bibendum. Proinde tincidunt
                dolor tellus, sit amet porta neque varius vitae. Seduse molestie
                lacus id lacinia tempus. Vestibulum accumsan facilisis lorem, et
                mollis diam pretium gravida. In facilisis vitae tortor id vulput
                ate. Proin ornare arcu in sollicitudin pharetra. Crasti molestie

varchar(1024)   Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie
                vestibulum massa. Nullam dignissim elementum molestie. Vehiculas
                velit metus, sit amet tristique purus condimentum eleifend. Quis
                que mollis magna vel massa malesuada bibendum. Proinde tincidunt
                dolor tellus, sit amet porta neque varius vitae. Seduse molestie
                lacus id lacinia tempus. Vestibulum accumsan facilisis lorem, et
                mollis diam pretium gravida. In facilisis vitae tortor id vulput
                ate. Proin ornare arcu in sollicitudin pharetra. Crasti molestie
                dapibus leo lobortis eleifend. Vivamus vitae diam turpis. Vivamu
                nec tristique magna, vel tincidunt diam. Maecenas elementum semi
                quam. In ut est porttitor, sagittis nulla id, fermentum turpist.
                Curabitur pretium nibh a imperdiet cursus. Sed at vulputate este
                proin fermentum pretium justo, ac malesuada eros et Pellentesque
                vulputate hendrerit molestie. Aenean imperdiet a enim at finibus
                fusce ut ullamcorper risus, a cursus massa. Nunc non dapibus vel
                Lorem ipsum dolor sit amet, consectetur Praesent ut ultrices sit
Kit
quelle
31

Der beste Wert ist derjenige, der für die in der zugrunde liegenden Domäne definierten Daten geeignet ist.

Für einige Domains VARCHAR(10)ist das NameAttribut richtig , für andere Domains VARCHAR(255)möglicherweise die beste Wahl.

Oded
quelle
15

Wenn Sie die Antwort von a_horse_with_no_name hinzufügen, finden Sie möglicherweise Folgendes von Interesse ...

Es macht keinen Unterschied, ob Sie eine Spalte als VARCHAR (100) oder VACHAR (500) deklarieren.

-- try to create a table with max varchar length
drop table if exists foo;
create table foo(name varchar(65535) not null)engine=innodb;

MySQL Database Error: Row size too large.

-- try to create a table with max varchar length - 2 bytes for the length
drop table if exists foo;
create table foo(name varchar(65533) not null)engine=innodb;

Executed Successfully

-- try to create a table with max varchar length with nullable field
drop table if exists foo;
create table foo(name varchar(65533))engine=innodb;

MySQL Database Error: Row size too large.

-- try to create a table with max varchar length with nullable field
drop table if exists foo;
create table foo(name varchar(65532))engine=innodb;

Executed Successfully

Vergessen Sie nicht die Längenbytes und das nullbare Byte, also:

name varchar(100) not null wird 1 Byte (Länge) + bis zu 100 Zeichen (lateinisch1) sein

name varchar(500) not null wird 2 Bytes (Länge) + bis zu 500 Zeichen (latin1) sein

name varchar(65533) not null wird 2 Bytes (Länge) + bis zu 65533 Zeichen (latin1) sein

name varchar(65532) wird 2 Bytes (Länge) + bis zu 65532 Zeichen (Latin1) + 1 Null-Byte sein

Hoffe das hilft :)

Jon Black
quelle
Sie verwenden MySQL und die Frage bezieht sich auf MSSQL
Bogdan Mart
6

Wenden Sie sich immer an Ihren Business Domain-Experten. Wenn Sie es sind, suchen Sie nach einem Industriestandard. Wenn es sich bei der fraglichen Domain beispielsweise um den Familiennamen (Nachname) einer natürlichen Person handelt, würde ich für ein britisches Unternehmen zum gehen britischen Govtalk-Datenstandardkatalog nach Personeninformationen suchen und feststellen, dass ein Familienname zwischen 1 und 35 Zeichen lang ist .

eines Tages, wenn
quelle
3

Ich habe dies in letzter Zeit nicht überprüft, aber ich weiß in der Vergangenheit mit Oracle, dass der JDBC-Treiber während der Abfrageausführung einen Teil des Speichers reservieren würde, um die zurückkommende Ergebnismenge zu speichern. Die Größe des Speicherblocks hängt von den Spaltendefinitionen und der Abrufgröße ab. Die Länge der varchar2-Spalten beeinflusst also, wie viel Speicher reserviert ist. Dies verursachte vor Jahren schwerwiegende Leistungsprobleme für mich, da wir immer varchar2 (4000) (damals das Maximum) verwendeten und die Speicherbereinigung viel weniger effizient war als heute.

user1041892
quelle
-2

In gewissem Sinne haben Sie Recht, obwohl alles, was weniger als 2 ^ 8 Zeichen enthält, immer noch als Datenbyte registriert wird.

Wenn Sie den Basischarakter berücksichtigen, der mit einem VARCHAR <255 etwas übrig lässt, das dieselbe Menge an Speicherplatz verbraucht.

255 ist eine gute Basisdefinition, es sei denn, Sie möchten übermäßige Eingaben besonders einschränken.

Dale Willis
quelle
" obwohl alles, was weniger als 2 ^ 8 Zeichen enthält, immer noch als Datenbyte registriert wird " - falsch. In der Datenbank werden nur so viele Zeichen gespeichert, wie in einem VARCHAR-Typ angegeben sind. Beim Deklarieren einer Spalte wird kein Speicherplatz "registriert", reserviert oder initialisiert .
a_horse_with_no_name