Gibt es einen Vorteil von Varchar (500) gegenüber Varchar (8000)?

90

Ich habe dies in MSDN-Foren und hier nachgelesen und bin mir immer noch nicht sicher. Ich denke, das ist richtig: Varchar (max) wird als Textdatentyp gespeichert, was Nachteile hat. Nehmen wir also an, Ihr Feld wird zuverlässig weniger als 8000 Zeichen enthalten. Wie ein BusinessName-Feld in meiner Datenbanktabelle. In Wirklichkeit wird ein Firmenname wahrscheinlich immer unter 500 Zeichen liegen (eine Zahl aus meinem Hut ziehen). Es scheint, als ob viele Varchar-Felder, auf die ich stoße, deutlich unter die Anzahl von 8.000 Zeichen fallen.

Soll ich dieses Feld also zu einem Varchar (500) anstelle von Varchar (8000) machen? Nach meinem Verständnis von SQL gibt es keinen Unterschied zwischen diesen beiden. Um das Leben einfacher zu machen, möchte ich alle meine Varchar-Felder als Varchar (8000) definieren. Hat das irgendwelche Nachteile?

Verwandte: Größe der Varchar-Spalten (ich hatte nicht das Gefühl, dass diese meine Frage beantwortet hat).

jcollum
quelle
6
Stellen Sie sich vor, Sie versuchen, einen 500 Zeichen langen Firmennamen auf eine Visitenkarte zu schreiben ... :)
OMG Ponies
2
@OMG Ponys: Jedes Mal, wenn ich deinen Benutzernamen sehe, kichere ich. Was hast du gesagt? (Nur ein Scherz)
JCollum
4
@jcollum: SpaceMan Spiff wird immer meine Stimme bekommen. Das ist nicht wahr - jeder Calvin & Hobbes wird es tun, besonders aber die schneeskulpturierenden. Oder der Tyranosaurus, der eine F-14 fliegt. Aber ich schweife ab ...
OMG Ponys

Antworten:

19

Vom Standpunkt der Verarbeitung aus macht es keinen Unterschied, varchar (8000) gegenüber varchar (500) zu verwenden. Es ist eher eine "gute Praxis", eine maximale Länge zu definieren, die ein Feld enthalten soll, und Ihren Varchar auf diese Länge zu bringen. Dies kann zur Unterstützung der Datenvalidierung verwendet werden. Wenn Sie beispielsweise eine staatliche Abkürzung mit 2 Zeichen oder eine Postleitzahl mit 5 oder 9 Zeichen festlegen. Früher war dies eine wichtigere Unterscheidung, wenn Ihre Daten mit anderen Systemen oder Benutzeroberflächen interagierten, bei denen die Feldlänge kritisch war (z. B. ein Mainframe-Flatfile-Dataset), aber heutzutage denke ich, dass dies mehr Gewohnheit als alles andere ist.

BBlake
quelle
3
Sinnvoll ... für Dinge, die natürlich eine maximale Länge haben. Aber was machst du, wenn die maximale Länge nicht offensichtlich ist? ZB ein Firmenname.
JCollum
2
Wenn ich für so etwas keine Möglichkeit sehe, die mögliche Größe vorherzusagen, werde ich normalerweise je nach Art der Daten einen Varchar (8000) oder Varchar (max) verwenden
BBlake
4
Es scheint, dass dies einen Unterschied in der Leistung macht, auch im Jahr 2017: dba.stackexchange.com/a/162117/1822
a_horse_with_no_name
1
Neuere Antworten zeigen , dass es sind Kosten: es wirkt Optimierungslogik Antwort des Martin Smith und auch erwähnt 8K Gesamtzeilengröße Aspekte berücksichtigen gbn und Oliver .
ToolmakerSteve
123

Ein Beispiel, bei dem dies einen Unterschied machen kann, besteht darin, dass eine Leistungsoptimierung verhindert werden kann, bei der vermieden wird, dass Tabellen mit After-Triggern Informationen zur Zeilenversionierung hinzugefügt werden.

Dies wird hier von SQL Kiwi behandelt

Die tatsächliche Größe der gespeicherten Daten spielt keine Rolle - es kommt auf die potenzielle Größe an.

In ähnlicher Weise war es bei Verwendung speicheroptimierter Tabellen seit 2016 möglich, LOB-Spalten oder Kombinationen von Spaltenbreiten zu verwenden, die möglicherweise die Eingangsgrenze überschreiten könnten, jedoch mit einer Strafe verbunden sind.

(Max) Spalten werden immer außerhalb der Zeile gespeichert. Wenn für andere Spalten die Datenzeilengröße in der Tabellendefinition 8.060 Byte überschreiten kann, schiebt SQL Server die größten Spalten variabler Länge aus der Zeile. Auch hier hängt es nicht von der Menge der Daten ab, die Sie dort speichern.

Dies kann sich stark negativ auf den Speicherverbrauch und die Leistung auswirken

Ein weiterer Fall, in dem das Überdeklarieren von Spaltenbreiten einen großen Unterschied machen kann, ist, ob die Tabelle jemals mit SSIS verarbeitet wird. Der für Spalten mit variabler Länge (nicht BLOB) zugewiesene Speicher ist für jede Zeile in einem Ausführungsbaum festgelegt und entspricht der angegebenen maximalen Länge der Spalten, was zu einer ineffizienten Verwendung von Speicherpuffern führen kann (Beispiel) . Während der SSIS-Paketentwickler eine kleinere Spaltengröße als die Quelle deklarieren kann, wird diese Analyse am besten im Voraus durchgeführt und dort durchgesetzt.

Zurück in der SQL Server-Engine selbst ist ein ähnlicher Fall, dass SQL Server bei der Berechnung der Speicherzuweisung für Zuweisungen für SORTOperationen davon ausgeht, dass varchar(x)Spalten im Durchschnitt x/2Bytes verbrauchen .

Wenn die meisten Ihrer varcharSpalten voller sind, kann dies dazu führen, dass die sortVorgänge ausgeführt werden tempdb.

In Ihrem Fall, wenn Ihre varcharSpalten als 8000Bytes deklariert sind, aber tatsächlich einen Inhalt haben, der viel geringer ist als der, wird Ihrer Abfrage Speicher zugewiesen, den sie nicht benötigt, was offensichtlich ineffizient ist und zu Wartezeiten auf Speicherzuweisungen führen kann.

Dies wird in Teil 2 von SQL Workshops Webcast 1 behandelt, der hier heruntergeladen werden kann oder siehe unten.

use tempdb;

CREATE TABLE T(
id INT IDENTITY(1,1) PRIMARY KEY,
number int,
name8000 VARCHAR(8000),
name500 VARCHAR(500))

INSERT INTO  T 
(number,name8000,name500)
SELECT number, name, name /*<--Same contents in both cols*/
FROM master..spt_values

SELECT id,name500
FROM T
ORDER BY number

Bildschirmfoto

SELECT id,name8000
FROM T
ORDER BY number

Bildschirmfoto

Martin Smith
quelle
1
Wenn also fast alle meine Werte 3 oder 4 Zeichen sind, 4 Zeichen nie überschreiten dürfen und ich vermeiden möchte, dass "Sortiervorgänge auf Tempdb übertragen werden", deklariere ich meine Spalte VARCHAR (8) und verwende eine CHECK-Einschränkung, um diese Spalte zu erzwingen Die Breite darf 4 Zeichen nicht überschreiten. Was denken Sie?
AK
12
@AlexKuznetsov - Für diese Situation würde ich sie deklarieren, da char(4)es ohnehin 2 Bytes Overhead pro Variablenspalte gibt.
Martin Smith
9

Abgesehen von Best Practices (Antwort von BBlake)

  • Mit DDL erhalten Sie Warnungen zur maximalen Zeilengröße (8060) und zur Indexbreite (900 Byte)
  • DML stirbt, wenn Sie diese Grenzwerte überschreiten
  • ANSI PADDING ON ist die Standardeinstellung, damit Sie am Ende eine ganze Menge Leerzeichen speichern können
gbn
quelle
38
Nur zur Verdeutlichung von ANSI PADDING ON: Bei Verwendung von nvarcharund type varcharbedeutet dies nur, dass nachgestellte Leerzeichen beim Einfügen beibehalten werden - nicht, dass die Werte wie in charund mit Leerzeichen auf die Größe der Spalte aufgefüllt werden nchar.
Ben M
9

Große Spalten haben einige Nachteile, die etwas weniger offensichtlich sind und Sie möglicherweise etwas später bemerken:

  • Alle Spalten, die Sie in einem INDEX verwenden, dürfen 900 Byte nicht überschreiten
  • Alle Spalten in einer ORDER BY- Klausel dürfen 8060 Byte nicht überschreiten. Dies ist etwas schwer zu verstehen, da dies nur für einige Spalten gilt. Weitere Informationen finden Sie unter Überschreitung der Zeilengröße in SQL 2008 R2.
  • Wenn die Gesamtzeilengröße 8060 Byte überschreitet, wird für diese Zeile ein " Seitenverlust " angezeigt. Dies kann sich auf die Leistung auswirken (Eine Seite ist eine Zuordnungseinheit in SQLServer und auf 8000 Byte + etwas Overhead festgelegt. Das Überschreiten ist nicht schwerwiegend, aber es fällt auf, und Sie sollten versuchen, dies zu vermeiden, wenn Sie dies leicht können.)
  • Viele andere interne Datenstrukturen, Puffer und nicht zuletzt Ihre eigenen Variablen und Tabellenvariablen müssen diese Größen widerspiegeln. Bei übermäßigen Größen kann eine übermäßige Speicherzuweisung die Leistung beeinträchtigen

Versuchen Sie in der Regel, mit der Spaltenbreite konservativ umzugehen. Wenn es zu einem Problem wird, können Sie es leicht erweitern, um es den Anforderungen anzupassen. Wenn Sie später Speicherprobleme bemerken, kann es später unmöglich werden, eine breite Spalte zu verkleinern, ohne Daten zu verlieren, und Sie wissen nicht, wo Sie anfangen sollen.

Überlegen Sie in Ihrem Beispiel für die Firmennamen, wo Sie sie anzeigen können. Gibt es wirklich Platz für 500 Zeichen? Wenn nicht, macht es wenig Sinn, sie als solche zu speichern. http://en.wikipedia.org/wiki/List_of_companies_of_the_United_States listet einige Firmennamen auf und die maximale Anzahl beträgt ca. 50 Zeichen. Also würde ich 100 für die Spalte max verwenden. Vielleicht eher wie 80.

Oliver
quelle
2

Idealerweise möchten Sie kleiner werden, bis zu einer angemessenen Größe (500 ist nicht ausreichend groß) und sicherstellen, dass die Client-Validierung abfängt, wenn die Daten zu groß werden, und einen nützlichen Fehler senden.

Während der varchar tatsächlich keinen Speicherplatz in der Datenbank für den nicht verwendeten Speicherplatz reserviert, erinnere ich mich an Versionen von SQL Server, bei denen es darum geht, dass Datenbankzeilen breiter als eine bestimmte Anzahl von Bytes sind (nicht an die genaue Anzahl erinnern) und tatsächlich weggeworfen werden Welche Daten auch immer nicht passten. Eine bestimmte Anzahl dieser Bytes war für interne SQL Server-Aufgaben reserviert.

Otis
quelle
Das war früher auch ein viel größeres Problem. Aber heutzutage ist der Platz wirklich billig, daher denke ich nicht, dass es ein so großes Problem ist, zumindest aus meiner Sicht.
BBlake
1
@jcollum: In Ihrem Beispiel scheinen 500 für einen Firmennamen nicht angemessen dimensioniert zu sein.
Otis
1
@BBlake: Unabhängig von den Speicherkosten spielt es keine Rolle, wie viel Speicher Sie haben, wenn SQL Server weiterhin Einschränkungen hinsichtlich der Zeilengröße aufweist. Sie können alles in Textblobs speichern, aber es gibt einige SQL-Operationen, die Sie mit einem Blob nicht ausführen können, die Sie mit einem Varchar ausführen können.
Otis
2
@Otis: Mein Punkt ist folgender: Es gibt keine tatsächliche Einschränkung für die Größe eines Firmennamens. Es sei denn, irgendwo gibt es ein Gesetz. In diesem Fall würde ich dieses Feld varchar (8000) erstellen und es einen Tag nennen. Mein Denken geht so: Echte Einschränkung? varchar (x). Keine wirkliche Einschränkung? Varchar (8000).
JCollum
24
Ich dachte, 30 Zeichen wären gut für Stadtnamen, bis ich El Pueblo de Nuestra Señora la Reina de los Ángeles del Río de Porciúncula
StuartLC