it-swarm.com.de

Gibt es irgendwelche Nachteile bei der Verwendung von nvarchar (MAX)?

In SQL Server 2005 ist es nachteilig, alle Zeichenfelder zu nvarchar (MAX) zu machen, anstatt explizit eine Länge anzugeben, z. nvarchar (255)? (Abgesehen von dem offensichtlichen, dass Sie die Feldlänge auf Datenbankebene nicht begrenzen können)

325
stucampbell

Dieselbe Frage wurde in den MSDN-Foren gestellt:

Aus dem Originalbeitrag (viel mehr Informationen dort):

Wenn Sie Daten in einer VARCHAR (N) -Spalte speichern, werden die Werte auf dieselbe Weise physisch gespeichert. Wenn Sie es jedoch in einer VARCHAR (MAX) -Spalte speichern, werden die Daten hinter dem Bildschirm als TEXT-Wert behandelt. Daher ist beim Umgang mit einem VARCHAR (MAX) -Wert eine zusätzliche Verarbeitung erforderlich. (nur wenn die Größe 8000 überschreitet)

VARCHAR (MAX) oder NVARCHAR (MAX) wird als 'großer Werttyp' betrachtet. Große Werttypen werden normalerweise außerhalb der Zeile gespeichert. Dies bedeutet, dass die Datenzeile einen Zeiger auf einen anderen Ort enthält, an dem der 'große Wert' gespeichert ist ...

143
David Kreps

Es ist eine faire Frage und er hat abgesehen von dem Offensichtlichen gesagt ...

Nachteile können sein:

Auswirkungen auf die Leistung Das Abfrageoptimierungsprogramm verwendet die Feldgröße, um den effizientesten Ausführungsplan zu ermitteln

"1. Die Speicherplatzzuweisung in den Erweiterungen und Seiten der Datenbank ist flexibel. Wenn Sie also mithilfe von update Informationen zum Feld hinzufügen, müsste Ihre Datenbank einen Zeiger erstellen, wenn die neuen Daten länger sind als die zuvor eingefügten. Dies wären die Datenbankdateien fragmentiert werden = geringere Leistung in fast allen Bereichen, vom Index bis zum Löschen, Aktualisieren und Einfügen. " http://sqlblogcasts.com/blogs/simons/archive/2006/02/28/Why-use-anything-but -varchar_2800_max_2900_.aspx

Auswirkungen auf die Integration - für andere Systeme ist die Integration in Ihre Datenbank schwierig. Unvorhersehbares Datenwachstum Mögliche Sicherheitsprobleme, z. Sie könnten ein System zum Absturz bringen, indem Sie den gesamten Speicherplatz belegen

Hier gibt es einen guten Artikel: http://searchsqlserver.techtarget.com/tip/1,289483,sid87_gci1098157,00.html

47
alexmac

Manchmal möchten Sie, dass der Datentyp den darin enthaltenen Daten einen Sinn verleiht.

Angenommen, Sie haben eine Spalte, die eigentlich nicht länger als 20 Zeichen sein sollte. Wenn Sie diese Spalte als VARCHAR (MAX) definieren, könnte eine unerwünschte Anwendung eine lange Zeichenfolge einfügen, die Sie niemals kennen oder auf irgendeine Weise verhindern würden.

Wenn Ihre Anwendung das nächste Mal diese Zeichenfolge verwendet, wird unter der Annahme, dass die Länge der Zeichenfolge für die Domäne, die sie darstellt, bescheiden und angemessen ist, ein unvorhersehbares und verwirrendes Ergebnis erzielt.

28
Bill Karwin

Basierend auf dem in der akzeptierten Antwort angegebenen Link sieht es so aus, als ob:

  1. 100 Zeichen, die in einem nvarchar(MAX) -Feld gespeichert sind, werden nicht anders als 100 Zeichen in einem nvarchar(100) -Feld gespeichert - die Daten werden inline gespeichert, und Sie müssen keine Daten lesen und schreiben 'out of row'. Also keine Sorge da.

  2. Wenn die Größe größer als 4000 ist, werden die Daten automatisch "out of row" gespeichert. Also auch da keine Sorgen.

Jedoch...

  1. Sie können keinen Index für eine nvarchar(MAX) -Spalte erstellen. Sie können die Volltextindizierung verwenden, jedoch keinen Index für die Spalte erstellen, um die Abfrageleistung zu verbessern. Für mich besiegelt dies den Deal ... es ist definitiv ein Nachteil, immer nvarchar (MAX) zu verwenden.

Fazit:

Wenn Sie eine Art "universelle Zeichenfolgenlänge" für die gesamte Datenbank benötigen, die indiziert werden kann und keinen Platz und keine Zugriffszeit verschwendet, können Sie nvarchar(4000) verwenden.

25
Tim Abell

Ich habe einige Artikel durchgesehen und darin ein nützliches Testskript gefunden: http://www.sqlservercentral.com/Forums/Topic1480639-1292-1.aspx Dann wurde es geändert, um NVARCHAR (10) mit NVARCHAR zu vergleichen (4000) vs NVARCHAR (MAX) und ich finde keinen Geschwindigkeitsunterschied, wenn ich angegebene Zahlen verwende, aber wenn ich MAX verwende. Sie können selbst testen. Ich hoffe das hilft.

SET NOCOUNT ON;

--===== Test Variable Assignment 1,000,000 times using NVARCHAR(10)
DECLARE @SomeString NVARCHAR(10),
        @StartTime DATETIME;
--=====         
 SELECT @startTime = GETDATE();
 SELECT TOP 1000000
        @SomeString = 'ABC'
   FROM master.sys.all_columns ac1,
        master.sys.all_columns ac2;
 SELECT testTime='10', Duration = DATEDIFF(ms,@StartTime,GETDATE());
GO
--===== Test Variable Assignment 1,000,000 times using NVARCHAR(4000)
DECLARE @SomeString NVARCHAR(4000),
        @StartTime DATETIME;
 SELECT @startTime = GETDATE();
 SELECT TOP 1000000
        @SomeString = 'ABC'
   FROM master.sys.all_columns ac1,
        master.sys.all_columns ac2;
 SELECT testTime='4000', Duration = DATEDIFF(ms,@StartTime,GETDATE());
GO
--===== Test Variable Assignment 1,000,000 times using NVARCHAR(MAX)
DECLARE @SomeString NVARCHAR(MAX),
        @StartTime DATETIME;
 SELECT @startTime = GETDATE();
 SELECT TOP 1000000
        @SomeString = 'ABC'
   FROM master.sys.all_columns ac1,
        master.sys.all_columns ac2;
 SELECT testTime='MAX', Duration = DATEDIFF(ms,@StartTime,GETDATE());
GO
19
QMaster

Stellen Sie es sich als eine weitere Sicherheitsstufe vor. Sie können Ihre Tabelle ohne Fremdschlüsselbeziehungen entwerfen - vollkommen gültig - und sicherstellen, dass die zugehörigen Entitäten vollständig in der Geschäftsschicht vorhanden sind. Fremdschlüssel werden jedoch als gute Entwurfspraxis angesehen, da sie eine weitere Einschränkungsstufe hinzufügen, falls die Geschäftsebene durcheinander geraten sollte. Gleiches gilt für die Feldgrößenbeschränkung und nicht für die Verwendung von varchar MAX.

13
Alex

Ein Grund, warum Sie KEINE Max- oder Textfelder verwenden sollten, ist, dass Sie keine Online-Indexneubildungen durchführen können , d. H. REBUILD WITH ONLINE = ON, auch mit SQL Server Enterprise Edition.

8
Nick Kavadias

Die Aufgabe der Datenbank besteht darin, Daten so zu speichern, dass sie vom Unternehmen verwendet werden können. Um diese Daten nützlich zu machen, muss sichergestellt werden, dass sie aussagekräftig sind. Das Zulassen, dass jemand eine unbegrenzte Anzahl von Zeichen für seinen Vornamen eingibt, stellt keine aussagekräftigen Daten sicher.

Es ist eine gute Idee, diese Einschränkungen in die Business-Schicht zu integrieren, dies stellt jedoch nicht sicher, dass die Datenbank intakt bleibt. Die einzige Möglichkeit, um sicherzustellen, dass die Datenregeln nicht verletzt werden, besteht darin, sie auf der niedrigstmöglichen Ebene in der Datenbank durchzusetzen.

4
Tom H

Eine schlechte Idee, wenn Sie wissen, dass das Feld in einem festgelegten Bereich von 5 bis 10 Zeichen liegt. Ich denke, ich würde nur max verwenden, wenn ich mir nicht sicher wäre, wie lang das sein würde. Zum Beispiel würde eine Telefonnummer niemals mehr als eine bestimmte Anzahl von Zeichen sein.

Können Sie ehrlich sagen, dass Sie über die ungefähren Längenanforderungen für jedes Feld in Ihrer Tabelle so unsicher sind?

Aber ich verstehe, dass es einige Felder gibt, die ich mit varchar (max) definitiv in Betracht ziehen würde.

Interessanterweise fassen die MSDN docs es ziemlich gut zusammen:

Verwenden Sie varchar, wenn die Größe der Spaltendateneinträge erheblich variiert. Verwenden Sie varchar (max), wenn die Größe der Spaltendateneinträge erheblich variiert und die Größe möglicherweise 8.000 Byte überschreitet.

Es gibt eine interessante Diskussion zu diesem Thema hier .

4
RichardOD

Das einzige Problem, das ich fand, war, dass wir unsere Anwendungen auf SQL Server 2005 entwickeln und in einem Fall SQL Server 2000 unterstützen müssen. Ich habe gerade gelernt, dass SQL hard way Server 2000 mag die MAX-Option für varchar oder nvarchar nicht.

4
mattruma

Ein Problem ist, dass der MAX nicht immer funktioniert, wenn Sie mit mehreren Versionen von SQL Server arbeiten müssen. Wenn Sie also mit älteren Datenbanken oder einer anderen Situation arbeiten, die mehrere Versionen umfasst, sollten Sie sehr vorsichtig sein.

3
TheTXI

Wie bereits erwähnt, handelt es sich in erster Linie um einen Kompromiss zwischen Speicher und Leistung. Zumindest in den meisten Fällen.

Es gibt jedoch mindestens einen weiteren Faktor, der bei der Auswahl von n/varchar (Max) anstelle von n/varchar (n) berücksichtigt werden sollte. Werden die Daten indiziert (z. B. ein Nachname)? Da die MAX-Definition als LOB betrachtet wird, ist nichts, was als MAX definiert ist, für die Indizierung verfügbar. und ohne Index wird jede Suche, bei der die Daten als Vergleichselement in einer WHERE-Klausel verwendet werden, zu einer vollständigen Tabellensuche gezwungen. Dies ist die schlechteste Leistung, die Sie bei der Suche nach Daten erzielen können.

3
Harry Cooper

1) Der SQL Server muss beim Umgang mit nvarchar (max) im Vergleich zu nvarchar (n), wobei n eine feldspezifische Zahl ist, mehr Ressourcen verwenden (zugewiesener Speicher und CPU-Zeit).

2) Was bedeutet das für die Leistung?

Unter SQL Server 2005 habe ich 13.000 Datenzeilen aus einer Tabelle mit 15 nvarchar (max) -Spalten abgefragt. Ich habe die Abfragen wiederholt zeitlich festgelegt und dann die Spalten in nvarchar (255) oder weniger geändert.

Die Abfragen vor der Optimierung lagen im Durchschnitt bei 2,0858 Sekunden. Die Abfragen nach der Änderung wurden in durchschnittlich 1,90 Sekunden zurückgegeben. Das waren etwa 184 Millisekunden mehr als bei der einfachen select * -Abfrage. Das ist eine Verbesserung von 8,8%.

3) Meine Ergebnisse stimmen mit einigen anderen Artikeln überein, in denen ein Leistungsunterschied festgestellt wurde. Abhängig von Ihrer Datenbank und der Abfrage kann der Prozentsatz der Verbesserung variieren. Wenn Sie nicht viele gleichzeitige Benutzer oder sehr viele Datensätze haben, ist der Leistungsunterschied für Sie kein Problem. Der Leistungsunterschied nimmt jedoch zu, wenn mehr Datensätze und gleichzeitige Benutzer vorhanden sind.

2
WWC

Wenn alle Daten in einer Zeile (für alle Spalten) niemals 8000 oder weniger Zeichen enthalten würden, sollte dies durch das Design auf Datenebene erzwungen werden.

Die Datenbank-Engine ist viel effizienter und verhindert, dass Blobs gespeichert werden. Je kleiner Sie eine Zeile einschränken können, desto besser. Je mehr Zeilen auf einer Seite gespeichert werden können, desto besser. Die Datenbank ist nur dann leistungsfähiger, wenn auf weniger Seiten zugegriffen werden muss.

1
Matt Spradley

Interessanter Link: Warum ein VARCHAR verwenden, wenn Sie TEXT verwenden können?

Es geht um PostgreSQL und MySQL, die Leistungsanalyse ist also anders, aber die Logik für "explizite Aussagen" ist immer noch gültig: Warum zwingen Sie sich, sich immer um etwas zu kümmern, das einen kleinen Prozentsatz der Zeit relevant ist? Wenn Sie eine E-Mail-Adresse in einer Variablen gespeichert haben, verwenden Sie eine Zeichenfolge und keine Zeichenfolge, die auf 80 Zeichen beschränkt ist.

1
orip

legacy-Systemunterstützung. Wenn Sie ein System haben, das die Daten verwendet und eine bestimmte Länge erwartet, ist die Datenbank ein guter Ort, um die Länge zu erzwingen. Dies ist nicht ideal, aber ältere Systeme sind manchmal nicht ideal. = P

1
Tony

Meine Tests haben gezeigt, dass es Unterschiede bei der Auswahl gibt.

CREATE TABLE t4000 (a NVARCHAR(4000) NULL);

CREATE TABLE tmax (a NVARCHAR(MAX) NULL);

DECLARE @abc4 NVARCHAR(4000) = N'ABC';

INSERT INTO t4000
SELECT TOP 1000000 @abc4
    FROM
    master.sys.all_columns ac1,
    master.sys.all_columns ac2;

DECLARE @abc NVARCHAR(MAX) = N'ABC';

INSERT INTO tmax
SELECT TOP 1000000 @abc
    FROM
    master.sys.all_columns ac1,
    master.sys.all_columns ac2;

SET STATISTICS TIME ON;
SET STATISTICS IO ON;

SELECT * FROM dbo.t4000;
SELECT * FROM dbo.tmax;
1
Kvasi

Ich hatte ein udf, das Zeichenfolgen auffüllte und die Ausgabe auf varchar (max) stellte. Wenn dies direkt verwendet wurde, anstatt auf die entsprechende Größe für die einzustellende Säule zurückzugießen, war die Leistung sehr schlecht. Am Ende habe ich das udf auf eine beliebige Länge mit einer großen Note gebracht, anstatt mich darauf zu verlassen, dass alle Aufrufer des udf die Zeichenfolge auf eine kleinere Größe umwandeln.

1
Cade Roux

Ein Nachteil besteht darin, dass Sie eine unvorhersehbare Variable entwerfen und die interne SQL Server-Datenstruktur, die progressiv aus Zeilen, Seiten und Ausdehnungen besteht, wahrscheinlich ignorieren, anstatt sie zu nutzen.

Was mich über Datenstrukturausrichtung in C nachdenken lässt, und dass es im Allgemeinen als eine gute Sache (TM) angesehen wird, sich der Ausrichtung bewusst zu sein. Ähnliche Idee, anderer Kontext.

MSDN-Seite für Seiten und Bereiche

MSDN-Seite für Zeilenüberlaufdaten

0
tsundoku

Der Hauptnachteil, den ich sehe, ist, dass wir sagen, Sie haben Folgendes:

Welches bietet Ihnen die meisten Informationen zu den für die Benutzeroberfläche benötigten Daten?

Diese

            CREATE TABLE [dbo].[BusData](
                [ID] [int] IDENTITY(1,1) NOT NULL,
                [RecordId] [nvarchar](MAX) NULL,
                [CompanyName] [nvarchar](MAX) NOT NULL,
                [FirstName] [nvarchar](MAX) NOT NULL,
                [LastName] [nvarchar](MAX) NOT NULL,
                [ADDRESS] [nvarchar](MAX) NOT NULL,
                [CITY] [nvarchar](MAX) NOT NULL,
                [County] [nvarchar](MAX) NOT NULL,
                [STATE] [nvarchar](MAX) NOT NULL,
                [Zip] [nvarchar](MAX) NOT NULL,
                [PHONE] [nvarchar](MAX) NOT NULL,
                [COUNTRY] [nvarchar](MAX) NOT NULL,
                [NPA] [nvarchar](MAX) NULL,
                [NXX] [nvarchar](MAX) NULL,
                [XXXX] [nvarchar](MAX) NULL,
                [CurrentRecord] [nvarchar](MAX) NULL,
                [TotalCount] [nvarchar](MAX) NULL,
                [Status] [int] NOT NULL,
                [ChangeDate] [datetime] NOT NULL
            ) ON [PRIMARY]

Oder dieses?

            CREATE TABLE [dbo].[BusData](
                [ID] [int] IDENTITY(1,1) NOT NULL,
                [RecordId] [nvarchar](50) NULL,
                [CompanyName] [nvarchar](50) NOT NULL,
                [FirstName] [nvarchar](50) NOT NULL,
                [LastName] [nvarchar](50) NOT NULL,
                [ADDRESS] [nvarchar](50) NOT NULL,
                [CITY] [nvarchar](50) NOT NULL,
                [County] [nvarchar](50) NOT NULL,
                [STATE] [nvarchar](2) NOT NULL,
                [Zip] [nvarchar](16) NOT NULL,
                [PHONE] [nvarchar](18) NOT NULL,
                [COUNTRY] [nvarchar](50) NOT NULL,
                [NPA] [nvarchar](3) NULL,
                [NXX] [nvarchar](3) NULL,
                [XXXX] [nvarchar](4) NULL,
                [CurrentRecord] [nvarchar](50) NULL,
                [TotalCount] [nvarchar](50) NULL,
                [Status] [int] NOT NULL,
                [ChangeDate] [datetime] NOT NULL
            ) ON [PRIMARY]
0
carlos martini