Warum nicht varchar (max) verwenden?

76

Ich bin ein bisschen altmodisch, wenn es um Datenbankdesign geht, also bin ich total dafür, die richtigen Datengrößen in Spalten zu verwenden. Als ich jedoch eine Datenbank für einen Freund überprüfte, bemerkte ich, dass er varchar(max)viel benutzte . Mein unmittelbarer Gedanke war nun, es ihm zurückzuwerfen und ihm zu sagen, er solle es ändern. Aber dann dachte ich darüber nach und konnte keinen guten Grund für ihn finden, es nicht zu verwenden (er hatte ein Falltyp-Tool verwendet, um die Datenbank zu generieren, wenn Sie sich fragen).

Ich habe das Thema der varchar(max)Verwendung untersucht und kann mir keinen guten Grund vorstellen, warum er es nicht verwendet.

Er verwendet die Spalten nicht für Indizes. Die Anwendung in der Datenbank hat Einschränkungen bei der Eingabe, sodass keine massiven Einträge in den Feldern zulässig sind.

Jede Hilfe wäre dankbar, wenn ich ihm helfen würde, das Licht zu sehen :).

AtaLoss
quelle
1
Siehe diese Antwort aus einem anderen Grund stackoverflow.com/questions/2009694/…
Martin Smith
Das ist interessant! Schade, dass ich das nicht früher gefunden habe. Vielen Dank!
AtaLoss
5
Zum einen: Sie können keinen Index für eine VARCHAR(MAX)Spalte
erstellen
1
Ich werde darauf hinweisen, dass es dumm ist, zu erwarten, dass die Anwendung immer die Eingabe steuert. Die Daten werden die Anwendung fast immer überdauern und die nächste Version der Anwendung hat möglicherweise nicht die richtigen Grenzwerte.
HLGEM

Antworten:

35

In meiner Antwort darauf geht es nicht um die Verwendung von Max, sondern um den Grund für VARCHAR (max) vs TEXT.

In meinem Buch; Zuallererst sollten Sie NVARCHAR oder NTEXT verwenden, es sei denn, Sie können absolut sicher sein, dass Sie niemals etwas anderes als englischen Text codieren und die Leute nicht auf Namen fremder Standorte verweisen.

Zweitens können Sie dies in den Feldern tun.

TEXT ist im Vergleich zu VARCHAR schwer zu aktualisieren, aber Sie profitieren von der Volltextindizierung und vielen cleveren Dingen.

Andererseits weist VARCHAR (MAX) eine gewisse Mehrdeutigkeit auf. Wenn die Größe der Zelle <8000 Zeichen beträgt, wird sie als Zeilendaten behandelt. Wenn es größer ist, wird es zu Speicherzwecken als LOB behandelt. Da Sie dies nicht wissen können, ohne RBAR abzufragen, gibt es möglicherweise Optimierungsstrategien für Orte, an denen Sie sich über Ihre Daten und die Anzahl der Lesevorgänge sicher sein müssen.

Andernfalls, wenn Ihre Verwendung relativ banal ist und Sie keine Probleme mit der Datengröße erwarten (IE verwenden Sie .Net und müssen sich daher nicht um die Größe Ihrer Zeichenfolge / Zeichen * -Objekte kümmern). dann ist die Verwendung von VARCHAR (max) in Ordnung.

Russ Clarke
quelle
4
Eine Sache, die mir beim Lesen von Artikeln darüber aufgefallen ist, war, dass beim Abfragen einer Tabelle die maximale Größe eines Datensatzes im Speicher gepuffert werden muss. Das könnte möglicherweise ein Problem sein, aber in heutigen Umgebungen mit mehreren Gigs (wenn nicht Terabyte) und mit RAM, das billig und einfach zu aktualisieren ist, reduziert es dieses Problem so ziemlich auf nichts.
AtaLoss
14
Diese Antwort scheint zu implizieren, dass die Volltextindizierung nur mit dem textDatentyp verwendet werden kann. Das ist nicht der Fall. textist ein veralteter Datentyp und hat keinen Vorteil gegenüber varchar(max)AFAIK.
Martin Smith
7
Ein weiterer Grund, TEXT / NTEXT nicht zu verwenden, ist, dass sie veraltet sind.
Aaron Bertrand
1
Kannst du das zitieren? Mir war nur bewusst, dass TEXT IN ROW veraltet war.
Russ Clarke
1
MSSQL Books Online : Text-, Text- und Bilddatentypen werden in einer zukünftigen Version von Microsoft SQL Server entfernt. Vermeiden Sie die Verwendung dieser Datentypen in neuen Entwicklungsarbeiten und planen Sie, Anwendungen zu ändern, die sie derzeit verwenden. Verwenden Sie stattdessen nvarchar (max), varchar (max) und varbinary (max).
Tibx
12

Es gibt eine Blog - Post , warum nicht varchar max verwenden hier

Bearbeiten

Der grundlegende Unterschied besteht darin, wo die Daten gespeichert werden. Eine SQL-Datenzeile hat eine maximale Größe von 8000 Byte (oder 8 KB). Dann kann kein 2 GB varchar (max) in der Datenzeile gespeichert werden. SQL Server speichert es "Out of Row".

Daher kann es zu Leistungseinbußen kommen, da sich die Daten nicht an derselben Stelle auf der Festplatte befinden (siehe: http://msdn.microsoft.com/en-us/library/ms189087.aspx)

Shiraz Bhaiji
quelle
1
Ja, das habe ich gelesen, aber ich hatte immer noch Fragen. Wenn der Code korrekt codiert ist, sodass die Daten in der Anwendung begrenzt sind, sollte er keine Leistungseinbußen aufweisen. Die Indizierung war kein Problem, und der letzte Punkt betraf das Design, um das sich mein Freund nicht kümmerte.
AtaLoss
1
Das varchar (max) wird nicht außerhalb der Zeile gespeichert, es sei denn, die in der Zeile gespeicherten Daten überschreiten die Zeilenbeschränkungen (die ungefähr 8 KB betragen). Das heißt, wenn Sie den Text "Hallo Welt" in einem varchar max in einer Tabelle mit 3 Spalten gespeichert haben, wird er wahrscheinlich nicht außerhalb der Zeile gespeichert.
AtaLoss
Der Grund, sie nicht zu verwenden, ist, dass sie nicht indiziert werden können. Es ist eine schlechte Praxis, nvarchar (max) oder varchar (max) zu verwenden, wenn Sie Daten erwarten, die diese benötigen.
HLGEM
Es ist nicht immer ein Performance-Hit. Tabellenscans werden beschleunigt, wenn die Zeilengröße abnimmt. Wenn das betreffende varchar (max) in Abfragen selten verwendet wird, bedeutet das Verschieben aus der Zeile einen Leistungsgewinn.
Johnnycrash
2
Der Leistungseinbruch ist die betriebliche Korrektheit wert, wenn Sie die Größe einer Zeichenfolge, die Sie möglicherweise in eine Zeile einfügen müssen, nicht vorhersehen können.
Binki
2

Wenn Sie in einer OLTP-Umgebung arbeiten, dreht sich alles um die Leistung. Von Overhead- und Optimierungsproblemen bis hin zu Indizierungsbeschränkungen und Abfrageengpässen. Die Verwendung eines varcahr (max) oder eines anderen LOB-Typs verstößt höchstwahrscheinlich gegen die meisten Best Practices für das Design. Es sei denn, es gibt einen bestimmten Geschäftsbedarf, der nicht durch die Verwendung eines anderen Typisierungsmechanismus bewältigt werden kann, und nur ein varchar (max) passt zum Warum sollten Sie dann Ihr System und Ihre Anwendungen den Overhead- und Leistungsproblemen aussetzen, die einem der LOB-Datentypen inhärent sind?

Wenn Sie andererseits in einer OLAP-Umgebung oder in einer Star Schema DW-Umgebung mit Dimensionstabellen mit Deskriptorfeldern arbeiten, die natürlich ausführlich sein müssen, dann ein varchar (max), solange Sie dies nicht zu einem Index hinzufügen. könnte nützlich sein. Trotzdem würde ich auch dann empfehlen, ein char (x) varchar (x) zu verwenden. Da es immer eine bewährte Methode ist, nur diese Ressourcen zu verwenden, müssen Sie unbedingt die Arbeit erledigen.

Scott Johnston
quelle
1

Sie sollten NICHT verwendet werden, es sei denn, Sie erwarten große Datenmengen. Hier ist der Grund dafür (direkt von Books Online):

Spalten der LOB-Datentypen ntext, text, varchar (max), nvarchar (max), varbinary (max), xml oder image können nicht als Schlüsselspalten für einen Index angegeben werden.

Wenn Sie die Leistung beeinträchtigen möchten, verwenden Sie nvarchar für alles.

HLGEM
quelle
2
Aber was ist, wenn Sie diese Spalte überhaupt nicht eingeben werden? Wenn Sie einen Textblock speichern, suchen Sie ihn wahrscheinlich in einer anderen Schlüsselspalte. Was ist das große Problem, wenn Indizes für Spalten erstellt werden müssen, in denen wahrscheinlich Freiformtext gespeichert wird und die WHEREnur zum Überprüfen angezeigt werden IS NULL?
Binki
@binki, der Rat ist, nicht für alles varchar (max) zu verwenden, da es Felder gibt, die Sie indizieren müssen. Es ist nur gedacht, wenn Sie große Datenmengen benötigen.
HLGEM
1
Nur weil es aus einem Online-Buch stammt, heißt das nicht, dass es richtig ist :) Ein weiteres Beispiel für die manchmal korrekte Verwendung von (MAX) ist das Speichern von Zeichenfolgen aus einer Quelle (z. B. Blobs, NOSQL-Felder), deren Größe nicht angegeben ist. Ich weiß nicht, wie groß es sein kann. Und ich stimme @binki zu, es gibt oft Spalten, von denen Sie wissen, dass Sie sie niemals indizieren werden.
8forty
1

Redgate hat einen großartigen Artikel darüber geschrieben.
https://www.red-gate.com/simple-talk/sql/database-administration/whats-the-point-of-using-varcharn-anymore/

Schlussfolgerungen

  • Verwenden Sie gegebenenfalls VARCHAR (n) anstelle von VARCHAR (MAX), um ein gutes Design zu erzielen, wenn dies keine Leistungsvorteile bietet, und weil VARCHAR (MAX) -Daten nicht komprimiert werden
  • Das Speichern großer Zeichenfolgen dauert länger als das Speichern kleiner Zeichenfolgen.
  • Das Aktualisieren eines In-Row-VARCHAR-Werts (MAX) von unter 8.000 auf über 8.000 ist relativ langsam, aber der Unterschied für eine einzelne Transaktion ist wahrscheinlich nicht messbar.
  • Das Aktualisieren eines In-Row-VARCHAR-Werts (MAX) von über 8.000 auf unter 8.000 ist schneller als wenn die Tabelle so eingestellt ist, dass Daten außerhalb der Zeile gespeichert werden.
  • Die Verwendung der Option "Außerhalb der Zeile" für VARCHAR (MAX) führt zu langsameren Schreibvorgängen, bis die Zeichenfolgen sehr lang sind.
Donny V.
quelle
0

Ich weiß nicht, wie SQL Server große (deklarierte) Varchar-Felder aus Sicht der Leistung, des Speichers und des Speichers handhabt. Unter der Annahme, dass dies genauso effizient ist wie kleinere deklarierte Varchar-Felder, gibt es dennoch den Vorteil von Integritätsbeschränkungen.

Die Anwendung, die auf der Datenbank sitzt, soll Einschränkungen für die Eingabe haben, aber die Datenbank kann einen Fehler ordnungsgemäß melden, wenn die Anwendung diesbezüglich einen Fehler aufweist.

beim.
quelle
Dies ist ein guter Punkt, insbesondere wenn Sie keine verwaltete Sprache zum Lesen Ihrer Zeichenfolgen verwenden.
Russ Clarke
Das ist ein guter Punkt. Ich werde dies erwähnen, es wird in c # 3.5 oder 4 entwickelt (ich glaube, ich sollte ihn fragen).
AtaLoss
@RussClarke Sind Zeichenfolgen mit variabler Länge wirklich nur verwaltet? Klingt so, als hätten Sie in nicht verwalteten Umgebungen noch nie eine Heap-Zuordnung festgestellt :-p.
Binki
@MartinSmith Das sind sehr kleine Leistungsverbesserungen. Auch der Blogger verwendet VARCHAR(MAX)mit Vergleichen und in der WHEREKlausel. Der Anwendungsfall, den ich erwarten würde, VARCHAR(MAX)ist etwas, das Sie nicht vergleichen würden oder WHEREin SQL - z. B. ein Blog-Inhaltsinhalt, eine Freiform-Textbeschreibung von etwas. Wenn Sie oder vergleichen möchten, WHEREhilft natürlich die Einschränkung. Sein Beispiel 'abc'könnte sogar in einen Vergleich zweier Ganzzahlen übersetzt werden. Das ist nicht die Art von Daten, die man in einen VARCHAR(MAX)
Binki
0

Der Unterschied ist in next:
VARCHAR(X)kann indiziert und in der MDF/NDFDatendatei gespeichert werden.
VARCHAR(MAX)kann nicht indiziert werden, da es ein hohes Volumen erreichen kann und dann als separate Datei und nicht in der MDF/NDFDatendatei gespeichert wird.

Vlad Kirov
quelle
6
Wo genau speichert MS SQL Ihrer Meinung nach LOB-Daten, wenn nicht in den MDF-Dateien?
0

   Es ist etwas altmodisch zu glauben, dass die Anwendung nur kurze Zeichenfolgen an die Datenbank weitergibt, und das macht es in Ordnung .

   In der heutigen Zeit MÜSSEN Sie damit rechnen, dass auf die Datenbank hauptsächlich von der aktuellen Anwendung zugegriffen wird. Möglicherweise gibt es jedoch eine zukünftige Version der Anwendung (weiß der Entwickler dieser Version, dass Zeichenfolgen unter einer bestimmten Länge gehalten werden müssen?).

   Sie MÜSSEN damit rechnen, dass Webdienste, ETL-Prozesse, LYNC to SQL und eine andere Anzahl bereits vorhandener und / oder noch nicht vorhandener Technologien für den Zugriff auf Ihre Datenbank verwendet werden.

   Generell versuche ich nicht über varchar (4000) zu gehen, weil es immerhin viertausend Zeichen sind. Wenn ich das überschreite, schaue ich nach anderen Datentypen, um zu speichern, was auch immer ich zu speichern versuche. Brent Ozar hat einige großartige Sachen darüber geschrieben .

   Trotzdem ist es wichtig, den Ansatz des aktuellen Designs für Ihre aktuellen Anforderungen zu bewerten, wenn Sie an einem Projekt arbeiten. Machen Sie sich ein Bild davon, wie die verschiedenen Teile funktionieren, verstehen Sie die Kompromisse verschiedener Ansätze und lösen Sie das vorliegende Problem. Das Üben eines großen Axioms kann zu einer blinden Haftung führen, die Sie in einen Lemming verwandeln kann .

Stephen Lauzon
quelle