Ich arbeite an einer Datenbank für eine kleine Web-App an meiner Schule mit SQL Server 2005
.
Ich sehe ein paar Denkschulen zum Thema varchar
vs nvarchar
:
- Verwenden
varchar
Sie diese Option, wenn Sie nicht mit vielen internationalisierten Daten arbeitennvarchar
. - Einfach
nvarchar
für alles verwenden.
Ich fange an, die Vorzüge von Ansicht 2 zu erkennen. Ich weiß, dass nvarchar doppelt so viel Platz einnimmt, aber das ist nicht unbedingt eine große Sache, da hier nur Daten für einige hundert Schüler gespeichert werden. Für mich scheint es am einfachsten zu sein, sich darüber keine Sorgen zu machen und einfach zuzulassen, dass alles nvarchar verwendet. Oder fehlt mir etwas?
sql-server
sql-server-2005
storage
varchar
nvarchar
Jason Baker
quelle
quelle
NVARCHAR
", und es kann sehr negative Auswirkungen auf die Leistung und die Hardwarekosten / -budgets haben. Ein paar Reihen, sogar ein paar Tausend, spielen keine Rolle. Die Systeme wachsen jedoch schneller als erwartet, sodass die derzeit akzeptierte Antwort einen schlechten Dienst für die Community darstellt. Danke dir.Antworten:
Verwenden Sie immer nvarchar.
Für die meisten Anwendungen benötigen Sie möglicherweise nie die Doppelbyte-Zeichen. Wenn Sie jedoch Doppelbyte-Sprachen unterstützen müssen und nur Einzelbyte-Unterstützung in Ihrem Datenbankschema haben, ist es sehr teuer, in Ihrer gesamten Anwendung Änderungen vorzunehmen.
Die Kosten für die Migration einer Anwendung von varchar nach nvarchar sind viel höher als der zusätzliche Speicherplatz, den Sie in den meisten Anwendungen verwenden.
quelle
Speicherplatz ist nicht das Problem ... aber Speicher und Leistung werden es sein. Doppelte Seitenlesungen, doppelte Indexgröße, seltsames LIKE und = konstantes Verhalten usw.
Müssen Sie chinesische usw. Skripte speichern? Ja oder Nein...
Und von MS BOL " Speicher- und Leistungseffekte von Unicode "
Bearbeiten :
Aktuelle SO-Frage, die hervorhebt, wie schlecht die Leistung von nvarchar sein kann ...
SQL Server verwendet eine hohe CPU, wenn in nvarchar-Zeichenfolgen gesucht wird
quelle
Sei konsequent! Die Verbindung eines VARCHAR mit NVARCHAR hat einen großen Leistungseinbruch.
quelle
nvarchar
zuvarchar
und dem Konvertierennvarchar
zuvarchar
und dem Beitritt zu gibtvarchar
. Es sei denn natürlich, Sie wollten in Spaltendatentypen konsistent sein, nicht beim Verknüpfen.VARCHAR
und ein drastischer Leistungseinbruch auftrittNVARCHAR
, sollte dies auf die Indizierung derVARCHAR
Spalte zusammen mit der für diese Spalte verwendeten Kollatierungsart (und damit auf den Index) zurückzuführen sein. Ich werde dieses Thema im folgenden Blog-Beitrag ausführlich behandeln: Auswirkungen auf Indizes beim Mischen von VARCHAR- und NVARCHAR-Typen .nvarchar wird einen erheblichen Overhead in Bezug auf Speicher, Speicher, Arbeitssatz und Indizierung haben. Wenn die Spezifikationen dies vorschreiben, wird dies wirklich niemals der Fall sein notwendig sein wird, stören Sie sich nicht.
Ich hätte keine feste Regel "immer nvarchar", da dies in vielen Situationen eine völlige Verschwendung sein kann - insbesondere ETL von ASCII / EBCDIC oder Bezeichner und Codespalten, bei denen es sich häufig um Schlüssel und Fremdschlüssel handelt.
Auf der anderen Seite gibt es viele Fälle von Spalten, in denen ich diese Frage sicher früh stellen würde, und wenn ich nicht sofort eine feste Antwort bekommen würde, würde ich die Spalte nvarchar machen.
quelle
Ich zögere, hier noch eine weitere Antwort hinzuzufügen, da es bereits einige gibt, aber einige Punkte müssen gemacht werden, die entweder nicht oder nicht klar gemacht wurden.
Erstens: Do nicht immer verwenden
NVARCHAR
. Das ist eine sehr gefährliche und oft kostspielige Einstellung. Und es ist nicht besser zu sagen, " Verwenden Sie niemals Cursor", da sie manchmal das effizienteste Mittel zur Lösung eines bestimmten Problems sind und die übliche Umgehung einerWHILE
Schleife fast immer langsamer ist als ein ordnungsgemäß durchgeführter Cursor.Sie sollten den Begriff "immer" nur verwenden, wenn Sie raten, "immer das zu tun, was für die Situation am besten ist". Zugegeben, das ist oft schwer zu bestimmen, insbesondere wenn versucht wird, kurzfristige Gewinne in der Entwicklungszeit (Manager: "Wir brauchen diese Funktion - von der Sie bis jetzt noch nichts wussten - vor einer Woche!") Mit Long in Einklang zu bringen -term Wartungskosten (Manager, der das Team anfangs unter Druck setzte, ein dreimonatiges Projekt in einem dreiwöchigen Sprint abzuschließen: "Warum haben wir diese Leistungsprobleme? Wie hätten wir möglicherweise X machen können, das keine Flexibilität hat? Wir können es uns nicht leisten." ein oder zwei Sprints, um dies zu beheben. Was können wir in einer Woche erledigen, damit wir zu unseren vorrangigen Elementen zurückkehren können? Und wir müssen definitiv mehr Zeit im Design verbringen, damit dies nicht immer passiert! ").
Zweitens: Die Antwort von @ gbn berührt einige sehr wichtige Punkte, die bei bestimmten Datenmodellierungsentscheidungen zu berücksichtigen sind, wenn der Pfad nicht 100% klar ist. Aber es gibt noch mehr zu beachten:
Platzverschwendung hat einen enormen Kaskadeneffekt auf das gesamte System. Ich habe einen Artikel geschrieben, der ausführlich auf dieses Thema eingeht : Disk Is Cheap! ORLY? (Kostenlose Registrierung erforderlich; Entschuldigung, ich kontrolliere diese Richtlinie nicht).
Drittens: Während sich einige Antworten fälschlicherweise auf den Aspekt "Dies ist eine kleine App" konzentrieren und andere zu Recht vorschlagen, "das zu verwenden, was angemessen ist", hat keine der Antworten dem OP eine echte Anleitung gegeben. Ein wichtiges Detail, das in der Frage erwähnt wird ist, dass dies eine Webseite für ihre Schule ist. Toll! Wir können also Folgendes vorschlagen:
NVARCHAR
da es mit der Zeit immer wahrscheinlicher wird, dass Namen aus anderen Kulturen an diesen Orten auftauchen.VARCHAR
mit der entsprechenden Codepage (welche) verwendet wird aus der Sortierung des Feldes bestimmt).INT
/TINYINT
da ISO-Codes eine feste Länge haben, für Menschen lesbar und gut standardisiert sind :), verwenden Sie sieCHAR(2)
für zwei Buchstabencodes undCHAR(3)
wenn Sie 3 Buchstabencodes verwenden. Und erwägen Sie die Verwendung einer binären Kollatierung wie zLatin1_General_100_BIN2
.VARCHAR
Sie diese , da es ein internationaler Standard ist, niemals Buchstaben außerhalb von AZ zu verwenden. Und ja, verwenden Sie esVARCHAR
auch dann, wenn Sie nur US-Postleitzahlen und nicht INT speichern, da Postleitzahlen keine Zahlen sind, sondern Zeichenfolgen, und einige von ihnen haben eine führende "0". Und erwägen Sie die Verwendung einer binären Kollatierung wie zLatin1_General_100_BIN2
.NVARCHAR
da beide jetzt Unicode-Zeichen enthalten können.Viertens: Jetzt, da Sie
NVARCHAR
Daten haben, die doppelt so viel Speicherplatz beanspruchen wie für Daten, die gut passenVARCHAR
("passt gut" = verwandelt sich nicht in "?"), Wuchs die Anwendung irgendwie wie von Zauberhand und jetzt gibt es Millionen von Datensätzen in mindestens einem dieser Felder, in denen die meisten Zeilen Standard-ASCII sind, aber einige Unicode-Zeichen enthalten, sodass SieNVARCHAR
Folgendes beachten müssen:Wenn Sie SQL Server 2008 - 2016 RTM verwenden und Enterprise Edition verwenden, ODER wenn Sie SQL Server 2016 SP1 (mit dem die Datenkomprimierung in allen Editionen verfügbar gemacht wurde) oder eine neuere Version verwenden, können Sie die Datenkomprimierung aktivieren . Die Datenkomprimierung kann (aber nicht "immer") Unicode-Daten in
NCHAR
undNVARCHAR
Felder komprimieren . Die bestimmenden Faktoren sind:NCHAR(1 - 4000)
undNVARCHAR(1 - 4000)
verwenden Sie das Standardkomprimierungsschema für Unicode , jedoch nur ab SQL Server 2008 R2 UND nur für IN ROW-Daten, nicht für OVERFLOW! Dies scheint besser zu sein als der reguläre ROW / PAGE-Komprimierungsalgorithmus.NVARCHAR(MAX)
undXML
(und ich denke auchVARBINARY(MAX)
,TEXT
undNTEXT
) Daten, die IN ROW sind (nicht außerhalb der Zeile in LOB- oder OVERFLOW-Seiten), können mindestens PAGE-komprimiert, aber nicht ROW-komprimiert werden. Natürlich hängt die PAGE-Komprimierung von der Größe des In-Row-Werts ab: Ich habe mit VARCHAR (MAX) getestet und festgestellt, dass 6000 Zeichen / Byte-Zeilen nicht komprimiert werden, 4000 Zeichen / Byte-Zeilen jedoch.Wenn Sie SQL Server 2005 oder 2008 - 2016 RTM und nicht Enterprise Edition verwenden, können Sie zwei Felder verwenden: eines
VARCHAR
und einesNVARCHAR
. Angenommen, Sie speichern URLs, bei denen es sich größtenteils um ASCII-Basiszeichen (Werte 0 bis 127) handelt und die daher inVARCHAR
Unicode-Zeichen passen , diese jedoch manchmal haben. Ihr Schema kann die folgenden 3 Felder enthalten:In diesem Modell wählen Sie nur aus der
[URL]
berechneten Spalte. Zum Einfügen und Aktualisieren bestimmen Sie, welches Feld verwendet werden soll, indem Sie prüfen, ob durch die Konvertierung der eingehende Wert geändert wird, der vomNVARCHAR
Typ sein muss:Sie können eingehende Werte in GZIP
VARBINARY(MAX)
eingeben und auf dem Weg nach draußen entpacken:COMPRESS
undDECOMPRESS
Funktionen verwenden, die auch GZip sind.Wenn Sie SQL Server 2017 oder höher verwenden, können Sie die Tabelle zu einem Clustered Columnstore-Index machen.
Obwohl dies noch keine praktikable Option ist, führt SQL Server 2019 die native Unterstützung für UTF-8 in
VARCHAR
/CHAR
datatypes ein. Derzeit gibt es zu viele Fehler, als dass sie verwendet werden könnten. Wenn sie jedoch behoben sind, ist dies für einige Szenarien eine Option . Eine detaillierte Analyse dieser neuen Funktion finden Sie in meinem Beitrag " Native UTF-8-Unterstützung in SQL Server 2019: Retter oder falscher Prophet? ".quelle
Für Ihre Anwendung ist nvarchar in Ordnung, da die Datenbankgröße klein ist. Zu sagen "benutze immer nvarchar" ist eine enorme Vereinfachung. Wenn Sie keine Dinge wie Kanji oder andere verrückte Charaktere speichern müssen, verwenden Sie VARCHAR, da dies viel weniger Platz beansprucht. Mein Vorgänger bei meinem aktuellen Job hat etwas mit NVARCHAR entworfen, wenn es nicht benötigt wurde. Wir haben es kürzlich auf VARCHAR umgestellt und nur an diesem Tisch 15 GB gespart (es wurde hoch geschrieben). Wenn Sie dann einen Index für diese Tabelle haben und diese Spalte einschließen oder einen zusammengesetzten Index erstellen möchten, haben Sie gerade Ihre Indexdatei vergrößert.
Seien Sie bei Ihrer Entscheidung nur nachdenklich. In der SQL-Entwicklung und bei Datendefinitionen scheint es selten eine "Standardantwort" zu geben (außer natürlich Cursor um jeden Preis zu vermeiden).
quelle
Da Ihre Anwendung klein ist, gibt es im Wesentlichen keine nennenswerten Kostensteigerungen bei der Verwendung von nvarchar gegenüber varchar, und Sie sparen sich potenzielle Kopfschmerzen, wenn Sie Unicode-Daten speichern müssen.
quelle
Allgemein gesagt; Beginnen Sie mit dem teuersten Datentyp mit den geringsten Einschränkungen. Setzen Sie es in Produktion . Wenn die Leistung ein Problem darstellt, finden Sie heraus, was tatsächlich in diesen
nvarchar
Spalten gespeichert ist . Gibt es dort Charaktere, die nicht passen würdenvarchar
? Wenn nicht, wechseln Sie zu varchar. Versuchen Sie nicht, vorab zu optimieren, bevor Sie wissen, wo der Schmerz ist. Ich vermute, dass die Wahl zwischen nvarchar / varchar Ihre Anwendung in absehbarer Zukunft nicht verlangsamen wird. Es wird andere Teile der Anwendung geben, in denen die Leistungsoptimierung Ihnen viel mehr Geld einbringt .quelle
In den letzten Jahren haben alle unsere Projekte NVARCHAR für alles verwendet, da alle diese Projekte mehrsprachig sind. Importierte Daten aus externen Quellen (z. B. eine ASCII-Datei usw.) werden vor dem Einfügen in die Datenbank in Unicode hochkonvertiert.
Ich habe noch keine leistungsbezogenen Probleme mit den größeren Indizes usw. festgestellt. Die Indizes verbrauchen zwar mehr Speicher, aber der Speicher ist billig.
Unabhängig davon, ob Sie gespeicherte Prozeduren verwenden oder SQL im laufenden Betrieb erstellen, stellen Sie sicher, dass allen Zeichenfolgenkonstanten N vorangestellt ist (z. B. SET @foo = N'Hello world. ';), Damit die Konstante auch Unicode ist. Dadurch wird eine Konvertierung des Zeichenfolgentyps zur Laufzeit vermieden.
YMMV.
quelle
Ich kann aus Erfahrung darüber sprechen, Vorsicht
nvarchar
. Sofern Sie dies nicht unbedingt benötigen, beeinträchtigt dieser Datenfeldtyp die Leistung in größeren Datenbanken. Ich habe eine Datenbank geerbt, die in Bezug auf Leistung und Speicherplatz beeinträchtigt war. Wir konnten die Größe einer 30-GB-Datenbank um 70% reduzieren! Es wurden einige andere Änderungen vorgenommen, um die Leistung zu verbessern, aber ich bin sichervarchar
, dass die auch hier erheblich geholfen haben. Wenn Ihre Datenbank das Potenzial hat, Tabellen auf über eine Million Datensätze zu vergrößern, halten Sie sichnvarchar
um jeden Preis fern .quelle
Ich beschäftige mich bei der Arbeit oft mit dieser Frage:
FTP-Feeds zu Inventar und Preisen - Artikelbeschreibungen und anderer Text befanden sich in nvarchar, als varchar einwandfrei funktionierte. Durch die Konvertierung in varchar wurde die Dateigröße fast halbiert und beim Hochladen wirklich geholfen.
Das obige Szenario hat gut funktioniert, bis jemand ein Sonderzeichen in die Artikelbeschreibung eingefügt hat (möglicherweise Marke, kann mich nicht erinnern)
Ich benutze nvarchar immer noch nicht jedes Mal über varchar. Wenn es Zweifel oder Potenzial für Sonderzeichen gibt, verwende ich nvarchar. Ich benutze Varchar meistens, wenn ich 100% Kontrolle darüber habe, was das Feld bevölkert.
quelle
Warum wurde UTF-8 in all diesen Diskussionen nicht erwähnt? Die Möglichkeit, die gesamte Unicode-Spanne von Zeichen zu speichern, bedeutet nicht, dass immer zwei Bytes pro Zeichen zugewiesen werden müssen (oder "Codepunkt", um den UNICODE-Begriff zu verwenden). Alle ASCII ist UTF-8. Überprüft SQL Server für VARCHAR () -Felder, ob der Text streng ASCII ist (dh das oberste Bytebit Null)? Ich würde nicht hoffen.
Wenn Sie dann Unicode speichern und Kompatibilität mit älteren Nur-ASCII-Anwendungen wünschen, würde ich die Verwendung von VARCHAR () und UTF-8 für das Wundermittel halten: Es benötigt nur dann mehr Speicherplatz, wenn dies erforderlich ist.
Für diejenigen unter Ihnen, die mit UTF-8 nicht vertraut sind, kann ich eine Grundierung empfehlen .
quelle
N
-präfixierte Typen). Sie haben keine Wahl zwischen UTF-8. Unicode-Codierungen (UTF-8, UCS-2 / UTF-16 und UTF-32) können auch nicht auf VARCHAR-Felder angewendet werden.Es gibt außergewöhnliche Fälle, in denen Sie den Datentyp absichtlich einschränken möchten, um sicherzustellen, dass er keine Zeichen aus einem bestimmten Satz enthält. Zum Beispiel hatte ich ein Szenario, in dem ich den Domänennamen in einer Datenbank speichern musste. Die Internationalisierung von Domain-Namen war zu diesem Zeitpunkt nicht zuverlässig, daher war es besser, die Eingabe auf der Basisebene einzuschränken und mögliche Probleme zu vermeiden.
quelle
Wenn Sie
NVARCHAR
nur verwenden, weil eine gespeicherte Systemprozedur dies erfordert, wobei das häufigste Auftreten unerklärlichsp_executesql
ist und Ihr dynamisches SQL sehr lang ist, sollten Sie aus Sicht der Leistung alle Zeichenfolgenmanipulationen (Verkettung, Ersetzung usw.) beimVARCHAR
Konvertieren durchführen das EndergebnisNVARCHAR
und füttere es in den proc-Parameter. Also nein, nicht immer benutzenNVARCHAR
!quelle