Zum Fußzeileninhalt springen
Iron Academy Logo
C# Allgemeine Probleme

Die Gefahren von nvarchar(max) in SQL für Entity Framework-Entwickler

Tim Corey
10m 27s

Beim Umgang mit nvarchar in SQL ignorieren Entwickler oft, wie sich dieser Datentyp auf die Leistung auswirkt - vor allem, wenn sie in C# mit Entity Framework arbeiten. In einem konzentrierten 10-minütigen Video mit dem Titel "Die Gefahren von nvarchar(max) in SQL für Entity Framework-Entwickler" untersucht Tim Corey die Auswirkungen der Verwendung von nvarchar(max) als Standardwert für String-Felder in einer SQL Server-Datenbank.

Dieser Artikel ist eine ausführliche Erläuterung von Tims Video, die sich ausschließlich auf seine Demonstrationen und Überlegungen stützt, mit Beispielen und Leistungsvergleichen. Wenn Sie sich auf nvarchar(max) verlassen, ohne zu verstehen, wie es unter der Haube funktioniert, wird dies ein Augenöffner sein.

Das Problem verstehen: Standardverhalten in Entity Framework

Tim beginnt mit der Beschreibung eines gängigen Entity Framework-Szenarios, in dem ein C#-Entwickler ein Modell mit Feldern wie FirstName und LastName definiert. Wenn die Tabelle in SQL Server mithilfe von Migrationen automatisch erstellt wird, setzt das generierte Schema diese Stringfelder standardmäßig auf nvarchar(max).

Wie Tim erklärt, geschieht dies, weil Entity Framework nicht weiß, welche Zeichenkettengröße zuzuordnen ist, und daher den sicheren Weg wählt, indem es standardmäßig die maximale Länge zuweist. Das bedeutet, dass jede nvarchar-Spalte bis zu 2^31-1 Zeichen zulässt, wobei die maximale Speichergröße im Gigabyte-Bereich liegt.

Diese Entscheidung scheint bequem zu sein, aber sie birgt gefährliche Leistungskosten.

Beispiel-Setup mit zwei Tabellen: nvarchar(max) vs. feste Länge

Um das Problem zu verdeutlichen, erstellt Tim zwei identische Tabellen:

  • Benutzer: mit nvarchar(50) für Vor- und Nachnamen.

  • UsersToTheMax: mit nvarchar(max) für dieselben Felder.

Bei 2:39 erklärt Tim, wie er beide Tabellen mit 1 Million identischer Zeilen mithilfe von Dapper befüllt und dabei sichergestellt hat, dass sich nur der Datentyp nvarchar unterscheidet.

Dieses Setup ermöglicht ihm einen konsistenten Vergleich zwischen einer Unicode-Spalte mit fester Länge und einer Max-Spalte mit variabler Länge.

Vergleich von Abfragen und Ausführungsplänen

Tim verwendet die folgende SQL-Abfrage für beide Tabellen:

SELECT * FROM dbo.Users ORDER BY LastName;
SELECT * FROM dbo.UsersToTheMax ORDER BY LastName;

Bei 3:34 schaltet er den eigentlichen Ausführungsplan ein, um zu analysieren, was SQL Server bei der Ausführung dieser Abfragen intern tut.

Hinweis: Bei diesem Test geht es nicht um die Gesamtausführungszeit auf verschiedenen Rechnern. Tim legt Wert darauf, Abfragen auf demselben Server mit denselben Daten zu vergleichen, um herauszufinden, wie nvarchar(max) die Leistung beeinflusst.

Die schockierenden Ergebnisse

Die Ausführungspläne zeigen einen großen Unterschied auf:

  • Die Abfrage zu nvarchar(50) verbraucht nur 2 % der Batch-Kosten.

  • Die Abfrage zu nvarchar(max) verbraucht satte 98 % der Kosten.

Wie Tim sagt, bedeutet dies, dass die maximale Abfrage 50 Mal teurer ist, wenn man bedenkt, wie SQL Server sie verarbeitet - auch wenn die Dateneinträge in den Spalten gleich und relativ klein sind.

In Bezug auf die CPU-Zeit:

  • Das Sortieren von nvarchar(50) dauert 107ms.

  • Das Sortieren von nvarchar(max) dauert 339ms.

Der größte Unterschied liegt jedoch in einem bestimmten Parallelitätsvorgang:

  • Feste Länge: 0.43s

  • Maximale Länge: 22.17s

Das ist über 50 Mal langsamer, selbst bei identischen Daten.

Unterschiede im Speicherverbrauch

Tim geht auf die Speicherzuteilung ein - wie viel Speicher SQL Server für jede Abfrage zuweist:

  • nvarchar(50) Abfrage: 340MB

  • nvarchar(max) Abfrage: 641MB

Dies allein ist schon ein Warnsignal, aber beim Testen von nicht zwischengespeicherten Spalten sind die Auswirkungen noch dramatischer:

  • Feste Länge bei FirstName: 357MB

  • Maximale Länge bei FirstName: 8.5 GB

Dieser Anstieg ist darauf zurückzuführen, dass SQL Server nicht weiß, wie groß der nvarchar-Wert sein kann, wenn er als max definiert ist, und daher einen größeren Speicherblock reserviert, um die maximale Größe unterzubringen.

Warum ist nvarchar(max) so kostspielig?

Um 9:15 Uhr erklärt Tim den Grund dafür. Der Datentyp nvarchar(max):

  • Unterstützt bis zu 2^31-1 Unicode-Zeichen und verbraucht bis zu 2 GB Speicherplatz.

  • Erfordert, dass SQL Server den Wert außerhalb der Zeile speichert, wenn er nicht passt, wobei ein Zeiger anstelle der direkten Speicherung in der Zeile verwendet wird.

  • Kann nicht auf die gleiche Weise indiziert werden wie Spalten mit fester Länge.

Daraus resultiert:

  • Sie können eine nvarchar(max)-Spalte nicht indizieren, was bedeutet, dass SQL Server den gesamten Datensatz ohne Optimierung sortieren oder filtern muss.

  • Dies betrifft Operationen wie ORDER BY, WHERE oder JOINs auf nvarchar(max)-Feldern.

Dieses Verhalten führt zu erheblichem Speicherverbrauch, CPU-Belastung und Verlangsamung - allein durch die Wahl der falschen Zeichendatenlänge.

Tim's abschließende Empfehlung

Wie Tim abschließend sagt:

"Stellen Sie sicher, dass Sie in Ihren Entity Framework-Abfragen die Größe aller Strings angeben."

Definieren Sie Ihre String-Eigenschaften immer mit einer maximalen Anzahl von Zeichen, z. B. nvarchar(100) oder nvarchar(255), je nach den erwarteten Daten. Diese kleine Änderung gewährleistet dies:

  • Optimierter Speicherplatz

  • Unterstützung für die Indizierung

  • Geringere Abfragekosten

  • Bessere Konsistenz der Leistung

Indem Sie eine angemessene Länge festlegen, machen Sie Ihr Datenbankschema effizienter und vermeiden die Fallstricke von faulen Standardeinstellungen.

Abschluss

Das Video von Tim Corey vermittelt eine wichtige Lektion: Die Verwendung von nvarchar(max) als Standardlänge für String-Felder in SQL kann die Leistung beeinträchtigen - ohne dass Sie es bemerken. SQL Server weist übermäßig viel Speicher zu, überspringt Indizes und erhöht die CPU-Kosten, selbst für normale Unicode-Texteinträge wie Namen oder Adressen.

Das Ergebnis? Verstehen Sie den Datentyp nvarchar und vermeiden Sie max, es sei denn, Sie benötigen ihn wirklich für Felder, die große Dokumente oder Inhalte mit variabler Länge speichern können.

Durch die Angabe der Stringgröße sparen Sie nicht nur Bytes und Speicherplatz, sondern machen Ihren Entity Framework- und SQL-Code auch effizienter, skalierbarer und robuster. Wenn Sie Tims Anleitung folgen, stellen Sie sicher, dass Ihre Anwendung nicht von vornherein langsam ist.

Für jeden, der mit Datenbanken in .NET arbeitet, ist dies eine bewährte Methode, die Teil des Standard-Toolkits sein sollte. Auf Tims Channel finden Sie weitere Videos zum Thema SQL.

Hero Worlddot related to Die Gefahren von nvarchar(max) in SQL für Entity Framework-Entwickler
Hero Affiliate related to Die Gefahren von nvarchar(max) in SQL für Entity Framework-Entwickler

Verdienen Sie mehr, indem Sie teilen, was Sie lieben

Erstellen Sie Inhalte für Entwickler, die mit .NET, C#, Java, Python oder Node.js arbeiten? Verwandeln Sie Ihr Fachwissen in ein zusätzliches Einkommen!

Iron Support Team

Wir sind 24 Stunden am Tag, 5 Tage die Woche online.
Chat
E-Mail
Rufen Sie mich an