varchar (max) überall?

80

Gibt es ein Problem damit, alle Ihre SQL Server 2008-Zeichenfolgenspalten varchar (max) zu machen? Meine zulässigen Zeichenfolgengrößen werden von der Anwendung verwaltet. Die Datenbank sollte nur so bleiben, wie ich sie gebe. Werde ich einen Leistungseinbruch hinnehmen, indem ich alle Zeichenfolgenspalten in SQL Server 2008 als vom Typ varchar (max) deklariere, unabhängig von der Größe der Daten, die tatsächlich in sie eingehen?

BowserKingKoopa
quelle
1
In meiner Lektüre klingt es so, als würden SQL Server-Varchar-Spalten sich selbst automatisch ändern. Wäre eine varchar (max) -Spalte, in der die maximale Länge eines bestimmten Werts 20 beträgt, nicht gleich einer varchar (20) -Spalte?
BowserKingKoopa

Antworten:

48

Wenn VARCHAR(MAX)Sie SQL Server verwenden, sagen Sie im Grunde, dass "Speichern Sie die Werte in diesem Feld so, wie Sie es am besten sehen". SQL Server wählt dann aus, ob Werte als reguläres VARCHARoder als LOB (großes Objekt) gespeichert werden sollen . Wenn die gespeicherten Werte weniger als 8.000 Byte betragen, behandelt SQL Server Werte im Allgemeinen als regulären VARCHARTyp.

Wenn die gespeicherten Werte sind zu groß , dann wird die Spalte der Seite , um LOB - Seiten zu vergießen off erlaubt, genau so , wie sie für andere LOB - Typen tun ( text, ntextund image) - wenn dies geschieht , dann weitere Seite liest erforderlich ist , um die Daten zu lesen , gespeichert in die zusätzlichen Seiten (dh es gibt eine Leistung penatly), dies geschieht jedoch nur, wenn die gespeicherten Werte zu groß sind .

Unter SQL Server 2008 oder höher können Daten auch bei Datentypen mit fester Länge (z. B. VARCHAR(3,000)) auf zusätzliche Seiten überlaufen. Diese Seiten werden jedoch als Zeilenüberlauf-Datenseiten bezeichnet und geringfügig anders behandelt.

Kurzversion: Aus Speichersicht gibt es für einige keinen Nachteil, VARCHAR(MAX)Over VARCHAR(N)zu verwenden N.

(Beachten Sie, dass dies auch für die anderen Feldtypen mit variabler Länge gilt NVARCHARund VARBINARY)

Zu Ihrer Information - Sie können keine Indizes für VARCHAR(MAX)Spalten erstellen

Justin
quelle
Dies gilt möglicherweise nur für nullfähige Felder. Jede Nicht-Null-Spalte varchar (max) oder nvarchar (max) erfordert 24 Byte zusätzliche feste Zuordnung. docs.microsoft.com/en-us/sql/t-sql/data-types/…
Liazy
33

Indizes dürfen für einen nicht mehr als 900 Byte breit sein. Sie können also wahrscheinlich nie einen Index erstellen. Wenn Ihre Daten weniger als 900 Byte betragen, verwenden Sie varchar (900).

Dies ist ein Nachteil: weil es gibt

  • wirklich schlechte Suchleistung
  • Keine eindeutigen Einschränkungen
gbn
quelle
Was aber, wenn die Spalte varchar (max) keine Werte enthält, die größer als 900 Byte sind? Würde es dann indizieren? Ich bin verwirrt, weil vieles, was ich lese, Varchar-Spaltentypen so klingen lässt, als würden sie sich bei der Dateneingabe automatisch bis zu ihrem Maximum anpassen. Dies wäre perfekt für das, was ich will, denn es ist die Anwendung, die das Maximum bestimmen sollte, nicht die Datenbank.
BowserKingKoopa
3
Sie erhalten eine Warnung, wenn Sie den Index erstellen, und einen Fehler, wenn Sie versuchen,> 900 einzufügen. Wenn Ihre Daten jedoch immer <900 sind, warum nicht 900 verwenden? Ja, sie werden jedoch als Zeichenfolgen variabler Länge gespeichert.
Gbn
8
Ich weiß nicht, ob meine Daten immer <900 sind. Das ist ein Problem der Geschäftslogik. Wenn sich diese Regel ändert, sollte ich sie in der Geschäftslogik ändern. Ich sollte nicht auch die Datenbank ändern müssen. Das ist sowieso mein Ziel. Um zu sehen, ob ich die Bedenken hinsichtlich der Zeichenfolgengröße aus der Datenbank entfernen kann, ohne dass ein merklicher Leistungseinbruch auftritt.
BowserKingKoopa
2
Wie oft ist es sinnvoll, eine lange Textspalte zu indizieren? Wäre es überhaupt sinnvoll, so etwas wie eine varchar (200) -Spalte zu indizieren? Schließlich wäre der Index selbst ineffizient. Die Notwendigkeit, nach langen "genauen Übereinstimmungen" zu suchen, scheint unwahrscheinlich. Und Mustersuchen würden nur dann von Vorteil sein, wenn der Beginn des Musters bekannt ist.
Desillusioniert
9

Simon Sabin hat vor einiger Zeit einen Beitrag dazu geschrieben. Ich habe jetzt nicht die Zeit, es zu greifen, aber Sie sollten danach suchen, da er zu dem Schluss kommt, dass Sie standardmäßig nicht varchar (max) verwenden sollten.

Bearbeitet: Simon hat ein paar Beiträge über varchar (max). Die Links in den Kommentaren unten zeigen dies ganz gut. Ich denke, das wichtigste ist http://sqlblogcasts.com/blogs/simons/archive/2009/07/11/String-concatenation-with-max-types-stops-plan-caching.aspx , das über den Effekt spricht von varchar (max) beim Plan-Caching. Das allgemeine Prinzip ist, vorsichtig zu sein. Wenn Sie nicht brauchen, dass es maximal ist, dann verwenden Sie nicht maximal - wenn Sie mehr als 8000 Zeichen benötigen, dann sicher ... machen Sie es.

Rob Farley
quelle
Der erste. Von OMG Ponys.
Rob Farley
Es tut mir leid, dass ich keine Zeit hatte, den eigentlichen Link zu finden. Ich wollte gerade in ein Meeting eintreten, als ich die Antwort abfeuern wollte.
Rob Farley
1
Und was noch wichtiger ist: sqlblogcasts.com/blogs/simons/archive/2009/07/11/…
Rob Farley
6

Für diese Frage speziell einige Punkte, die ich nicht erwähnt sehe.

  1. Wenn in R2 2005/2008/2008 R2 eine LOB-Spalte in einem Index enthalten ist, werden Online-Indexwiederherstellungen blockiert.
  2. Ab 2012 wurde die Einschränkung für die Neuerstellung von Online-Indizes aufgehoben, aber LOB-Spalten können nicht an der neuen Funktionalität teilnehmen. Hinzufügen von NOT NULL-Spalten als Online-Vorgang .
  3. Sperren für Zeilen mit Spalten dieses Datentyps können länger aufgehoben werden. ( mehr )

In meiner Antwort werden einige andere Gründe behandelt, warum nicht varchar(8000)überall .

  1. Bei Ihren Abfragen werden möglicherweise große Speicherzuweisungen angefordert, die nicht durch die Datengröße gerechtfertigt sind.
  2. Bei Tabellen mit Triggern kann eine Optimierung verhindert werden, bei der keine Versionierungs-Tags hinzugefügt werden.
Martin Smith
quelle
5

Ich habe die ähnliche Frage früher gestellt. habe einige interessante Antworten bekommen. Schau es dir hier an Es gab eine Site, auf der ein Typ über den Nachteil der Verwendung breiter Spalten sprach. Wenn Ihre Daten jedoch in der Anwendung begrenzt sind, haben meine Tests dies widerlegt. Die Tatsache, dass Sie keine Indizes für die Spalten erstellen können, bedeutet, dass ich sie nicht die ganze Zeit verwenden würde (persönlich würde ich sie überhaupt nicht so oft verwenden, aber in dieser Hinsicht bin ich ein bisschen puristisch). Wenn Sie jedoch wissen, dass nicht viel in ihnen gespeichert ist, denke ich nicht, dass sie so schlecht sind. Wenn Sie ein Recordset mit einem varchar (max) in Spalten sortieren (oder eine breite Spalte char oder varchar), kann dies zu Leistungseinbußen führen. Diese können (falls erforderlich) durch Indizes aufgelöst werden, Sie können jedoch keine Indizes für varchar (max) erstellen. Wenn Sie Ihre Spalten zukunftssicher machen möchten, setzen Sie sie einfach auf einen vernünftigen Wert. zB eine Namensspalte mit 255 Zeichen anstelle von max ...

AtaLoss
quelle
2

Es gibt noch einen weiteren Grund, die Verwendung von varchar (max) für alle Spalten zu vermeiden. Aus dem gleichen Grund, aus dem wir Prüfeinschränkungen verwenden (um zu vermeiden, dass Tabellen durch fehlerhafte Software oder Benutzereingaben mit Junk gefüllt werden), möchten wir uns vor fehlerhaften Prozessen schützen, die viel mehr Daten als beabsichtigt hinzufügen. Wenn zum Beispiel jemand oder etwas versucht hat, einem Stadtfeld 3.000 Bytes hinzuzufügen, wissen wir mit Sicherheit, dass etwas nicht stimmt, und möchten den Prozess stoppen, um ihn zum frühestmöglichen Zeitpunkt zu debuggen. Wir würden auch wissen, dass ein 3000-Byte-Städtename möglicherweise nicht gültig sein könnte und Berichte und dergleichen durcheinander bringen würde, wenn wir versuchen würden, ihn zu verwenden.

Larry Ness
quelle
1

Idealerweise sollten Sie nur das zulassen, was Sie brauchen. Das heißt, wenn Sie sicher sind, dass eine bestimmte Spalte (z. B. eine Spalte mit Benutzernamen) niemals länger als 20 Zeichen sein wird, können Sie mit einem VARCHAR (20) im Vergleich zu einem VARCHAR (MAX) die Datenbank Abfragen und Datenstrukturen optimieren.

Von MSDN: http://msdn.microsoft.com/en-us/library/ms176089.aspx

Variable-length, non-Unicode character data. n can be a value from 1 through 8,000. max indicates that the maximum storage size is 2^31-1 bytes.

Werden Sie wirklich jemals in die Nähe von 2 ^ 31-1 Bytes für diese Spalten kommen?

Leepowers
quelle
3
Ich denke nicht, dass es richtig ist, dies als "Zuweisen" zu charakterisieren. Die DB reserviert Ihnen sicherlich nirgendwo 2 ^ 31-1 Bytes.
Scott Stafford
1
"Eine Benutzername-Spalte [..] wird niemals länger als 20 Zeichen sein" - Gut, bis der Kunde eines Tages entscheidet, dass sie länger sein muss. Das haben wir alle schon durchgemacht. :)
Steve Smith