Was sind die Hauptleistungsunterschiede zwischen den Datentypen varchar und nvarchar SQL Server?

236

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 varcharvs nvarchar:

  1. Verwenden varcharSie diese Option, wenn Sie nicht mit vielen internationalisierten Daten arbeiten nvarchar.
  2. Einfach nvarcharfü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?

Jason Baker
quelle
ähnliche frage hier: stackoverflow.com/questions/312170/… EDIT von le dorfier: was interessanterweise zu genau dem gegenteiligen schluss kam.
Booji Boy
6
Verweis auf einen viel umfangreicheren Thread, der zu dem gegenteiligen Ergebnis kam. stackoverflow.com/questions/312170/…
dkretz
2
Jason: Ich hoffe , dies ist nicht eine unangemessene Anfrage, aber können Sie beachten Sie bitte die akzeptierte Antwort auf sich verändernde gbn des . JoeBarones Antwort ist aus vielen Gründen schrecklich falsch. Wenn es "akzeptiert" wird, führt es Anfänger dazu, schlechte Entscheidungen zu treffen. Es ist unnötig und verschwenderisch, "immer zu verwenden 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.
Solomon Rutzky

Antworten:

140

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.

Joe Barone
quelle
4
Es ist weitaus schwieriger, mehrsprachige Texte / Nachrichten, Zeitzonen, Maßeinheiten und Währungen zu unterstützen. Daher MUSS jeder diese IMMER vom ersten Tag an in seiner Anwendung codieren (auch wenn dies nur auf Ihrer Homepage der Fall ist App)!
KM.
82
Was ist mit Indexgröße, Speichernutzung usw.? Ich nehme an, Sie verwenden immer int, wenn Sie tinyint auch "nur für den Fall" verwenden könnten?
Gbn
99
Das Codieren / Planen einer mehrsprachigen Site (wenn Sie keine Ahnung haben, dass Sie sie jemals brauchen werden) ist so, als würden Sie allen jungen Erwachsenen sagen, dass sie für ihr erstes Auto einen großen 8-sitzigen, gasfressenden SUV kaufen sollen ... schließlich Sie könnten eines Tages heiraten und 6 Kinder haben. Ich möchte lieber die Leistung und Effizienz genießen, solange ich kann, und den Preis für das Upgrade bezahlen, wenn / wenn ich es brauche.
EJ Brennan
4
@cbmeeks: Ich codiere nicht für das, was ich nicht weiß. Aber wenn Sie es ohne merklichen Leistungseinbruch verwenden können, dann sind Ihre Datenbanken nicht groß genug, um eine Rolle zu spielen ...
gbn
60
Wenn Leute ihre Antwort mit dem Wort "Immer" beginnen, sollten Sie normalerweise alles ignorieren, was danach kommt. (Beachten Sie, dass ich diese Aussage mit dem Wort "normalerweise" begonnen habe :)
Brandon Moore
226

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

gbn
quelle
19
+1, wenn Ihre App international wird, haben Sie viele andere Probleme, die Sie bei der Suche / Ersetzung von nvarchar befürchten müssen: mehrsprachige Texte / Nachrichten, Zeitzonen, Maßeinheiten und Währung
KM.
2
Aber was ist, wenn Sie manchmal einen fremden Namen wie José oder Bjørn speichern müssen?
Qwertie
7
@ Qwertie: dann benutzt du nvarchar. Was Sie nicht tun, verwenden Sie es unnötig. Diese 2 Namen passen sowieso in varchar IIRC
gbn
6
Zu sagen, dass Speicherplatz kein Problem ist, gilt nicht für alle. Wir haben nvarchar in einer großen Bankanwendung mit Milliarden von Datensätzen, die über viele Jahre hinweg gespeichert wurden, unnötig unnötig eingesetzt. Mit teurem SAN-basiertem Speicher mit Replikation, Sicherung und Notfallwiederherstellung kann dies tatsächlich zu Kosten in Millionenhöhe für nvarchar vs varchar führen. Ganz zu schweigen davon, dass die Leistung stark beeinträchtigt wird (100%), wenn bei jedem Lesevorgang doppelt so viele Bytes von der Festplatte gelesen werden müssen.
Codemonkey
2
@codemonkey et al.: Ich habe alles getan, um das Problem der Speicherplatzverschwendung im folgenden Artikel ganzheitlich anzugehen: Disk Is Cheap! ORLY? (Eine kostenlose Registrierung ist jedoch erforderlich). Der Artikel soll dazu beitragen, die Situation zu verhindern, in die codemonkey in Bezug auf teuren Speicher auf Unternehmensebene geriet.
Solomon Rutzky
59

Sei konsequent! Die Verbindung eines VARCHAR mit NVARCHAR hat einen großen Leistungseinbruch.

Thomas Harlan
quelle
115
Wenn Sie Verknüpfungen für Zeichenfelder durchführen, hat Ihre Datenbank wahrscheinlich schlimmere Probleme als die Verwendung von nvarchar oder varchar im Allgemeinen.
Brandon Moore
@Thomas Harlan Ein einfacher Test zeigt mir, dass es keinen greifbaren Unterschied zwischen dem Beitritt nvarcharzu varcharund dem Konvertieren nvarcharzu varcharund dem Beitritt zu gibt varchar. Es sei denn natürlich, Sie wollten in Spaltendatentypen konsistent sein, nicht beim Verknüpfen.
Ajeh
1
@ajeh und Thomas: 1) "einfache" Tests sind oft irreführend, da sie keine Variationen abdecken, die Unterschiede im Verhalten verursachen. 2) Wenn beim Mischen VARCHARund ein drastischer Leistungseinbruch auftritt NVARCHAR, sollte dies auf die Indizierung der VARCHARSpalte 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 .
Solomon Rutzky
44

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.

Cade Roux
quelle
26

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 einer WHILESchleife 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:

  • Größe der Transaktionsprotokolldateien
  • Zeit für die Replikation (bei Verwendung der Replikation)
  • Zeit, die für ETL benötigt wird (wenn ETLing)
  • Zeit, die benötigt wird, um Protokolle an ein Remote-System zu senden und wiederherzustellen (wenn Sie den Protokollversand verwenden)
  • Größe der Backups
  • Zeitdauer, die zum Abschließen der Sicherung benötigt wird
  • Zeitdauer für eine Wiederherstellung (dies könnte eines Tages wichtig sein ;-)
  • Größe für Tempdb benötigt
  • Leistung von Triggern (für eingefügte und gelöschte Tabellen, die in Tempdb gespeichert sind)
  • Leistung der Zeilenversionierung (bei Verwendung von SNAPSHOT ISOLATION, da sich der Versionsspeicher in Tempdb befindet)
  • Möglichkeit, neuen Speicherplatz zu erhalten, wenn der CFO angibt, dass er letztes Jahr nur 1 Million US-Dollar für ein SAN ausgegeben hat und daher keine weiteren 250.000 US-Dollar für zusätzlichen Speicher autorisiert
  • Zeitdauer für INSERT- und UPDATE-Operationen
  • Zeitdauer für die Indexpflege
  • usw. usw. usw. usw.

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:

  • Felder für Studenten- und / oder Fakultätsnamen sollten wahrscheinlich vorhanden sein, NVARCHARda es mit der Zeit immer wahrscheinlicher wird, dass Namen aus anderen Kulturen an diesen Orten auftauchen.
  • Aber für Adresse und Städtenamen? Der Zweck der App wurde nicht angegeben (es wäre hilfreich gewesen), aber unter der Annahme, dass sich die Adressdatensätze, falls vorhanden, nur auf eine bestimmte geografische Region (dh eine einzelne Sprache / Kultur) beziehen, dann verwendenVARCHAR mit der entsprechenden Codepage (welche) verwendet wird aus der Sortierung des Feldes bestimmt).
  • Wenn Sie ISO-Codes für Bundesstaaten und / oder Länder speichern (keine Notwendigkeit zum Speichern INT/ TINYINTda ISO-Codes eine feste Länge haben, für Menschen lesbar und gut standardisiert sind :), verwenden Sie sie CHAR(2)für zwei Buchstabencodes und CHAR(3)wenn Sie 3 Buchstabencodes verwenden. Und erwägen Sie die Verwendung einer binären Kollatierung wie z Latin1_General_100_BIN2.
  • Wenn Sie Postleitzahlen (dh Postleitzahlen) speichern, verwenden VARCHARSie diese , da es ein internationaler Standard ist, niemals Buchstaben außerhalb von AZ zu verwenden. Und ja, verwenden Sie es VARCHARauch 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 z Latin1_General_100_BIN2.
  • Wenn Sie E-Mail-Adressen und / oder URLs speichern, verwenden Sie diese Option, NVARCHARda beide jetzt Unicode-Zeichen enthalten können.
  • und so weiter....

Viertens: Jetzt, da Sie NVARCHARDaten haben, die doppelt so viel Speicherplatz beanspruchen wie für Daten, die gut passen VARCHAR("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 Sie NVARCHARFolgendes beachten müssen:

  1. 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 NCHARund NVARCHARFelder komprimieren . Die bestimmenden Faktoren sind:

    1. NCHAR(1 - 4000)und NVARCHAR(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.
    2. NVARCHAR(MAX)und XML(und ich denke auch VARBINARY(MAX), TEXTund NTEXT) 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.
    3. Alle OFF ROW-Daten, LOB oder OVERLOW = Keine Komprimierung für Sie!
  2. Wenn Sie SQL Server 2005 oder 2008 - 2016 RTM und nicht Enterprise Edition verwenden, können Sie zwei Felder verwenden: eines VARCHARund eines NVARCHAR. Angenommen, Sie speichern URLs, bei denen es sich größtenteils um ASCII-Basiszeichen (Werte 0 bis 127) handelt und die daher in VARCHARUnicode-Zeichen passen , diese jedoch manchmal haben. Ihr Schema kann die folgenden 3 Felder enthalten:

      ...
      URLa VARCHAR(2048) NULL,
      URLu NVARCHAR(2048) NULL,
      URL AS (ISNULL(CONVERT(NVARCHAR([URLa])), [URLu])),
      CONSTRAINT [CK_TableName_OneUrlMax] CHECK (
                        ([URLa] IS NOT NULL OR [URLu] IS NOT NULL)
                    AND ([URLa] IS NULL OR [URLu] IS NULL))
    );

    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 vom NVARCHARTyp sein muss:

    INSERT INTO TableName (..., URLa, URLu)
    VALUES (...,
            IIF (CONVERT(VARCHAR(2048), @URL) = @URL, @URL, NULL),
            IIF (CONVERT(VARCHAR(2048), @URL) <> @URL, NULL, @URL)
           );
  3. Sie können eingehende Werte in GZIP VARBINARY(MAX)eingeben und auf dem Weg nach draußen entpacken:

    • Für SQL Server 2005 - 2014: Sie können SQLCLR verwenden. SQL # (eine SQLCLR-Bibliothek, die ich geschrieben habe) enthält Util_GZip und Util_GUnzip in der kostenlosen Version
    • Für SQL Server 2016 und höher: Sie können die integrierten Funktionen COMPRESSund DECOMPRESSFunktionen verwenden, die auch GZip sind.
  4. Wenn Sie SQL Server 2017 oder höher verwenden, können Sie die Tabelle zu einem Clustered Columnstore-Index machen.

  5. Obwohl dies noch keine praktikable Option ist, führt SQL Server 2019 die native Unterstützung für UTF-8 in VARCHAR/ CHARdatatypes 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? ".

Solomon Rutzky
quelle
7
Langsam klatschen. Einfach erstaunt, dass "immer nvarchar verwenden" 140 Stimmen bekam und das nicht. Großartige Arbeit an diesem Beitrag.
schizoid04
1
@ schizoid04 Danke. Um fair zu sein, wurde die akzeptierte Antwort 7 Jahre vor meiner veröffentlicht. Es gibt also viel Verkehr, der darüber abgestimmt hat (und / oder verschiedene andere), der nie zurückgekommen ist, um eine Neubewertung vorzunehmen. Dennoch bietet es einen sehr soliden Kontrapunkt zur Theorie der "Weisheit der Masse", die stimmbasierte Foren antreibt. Es gibt zu viele Fehlinformationen da draußen. Zum Beispiel dies auf DBA.SE. Die andere Antwort, die akzeptiert wurde, bevor ich meine gepostet habe, ist durch die engsten Definitionen "richtig", irreführend und enthält Informationen, die ich in meiner widerlege, aber meine übertrifft.
Solomon Rutzky
22

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).

WebMasterP
quelle
10

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.

tbreffni
quelle
8

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 nvarcharSpalten gespeichert ist . Gibt es dort Charaktere, die nicht passen würden varchar? 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 .

Kjetil Klaussen
quelle
7

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.

devstuff
quelle
4
Sie haben wahrscheinlich nicht mehrere hundert Millionen Datensätze in den Tabellen, mit denen Sie arbeiten. Ich bin damit einverstanden, dass für die meisten Apps die Standardeinstellung von nvarchar in Ordnung ist, aber nicht alle.
Brandon Moore
7

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 sicher varchar, 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 sich nvarcharum jeden Preis fern .

JA
quelle
4

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.

K Richard
quelle
3

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 .

Tevya
quelle
2
Was Sie vorschlagen, funktioniert möglicherweise für einige Anwendungen, aber Sie müssen auch die Auswirkungen einer zusätzlichen Codierungsschicht auf die Art und Weise berücksichtigen, wie SQL-Text verarbeitet wird. Insbesondere werden Kollatierungen, Suchen und Musterabgleich durchgeführt. Wenn Berichte für die Datenbank ausgeführt werden, werden die Multi-Byte-Zeichen durch Standard-Berichterstellungstools nicht korrekt verarbeitet. Und Massenimporte und -exporte können erfolgen. Ich denke, dass dieses Programm auf lange Sicht mehr Probleme bereiten kann, als es wert ist.
Jeffrey L Whitledge
1
Es ist nicht möglich, UTF-8 in VARCHAR-Spalten zu speichern. MSSQL wird immer Ihre UTF-8 - Daten an die Spaltensortierung konvertieren. Wenn Sie die Sortierung durcheinander bringen (z. B. versuchen, CP1252 in Latin_1 zu speichern), funktioniert die Konvertierung nicht und Sie erhalten zusätzliche Bytes in Ihren Daten. Es scheint gut zu funktionieren, wenn Sie latin_1 in UTF-8 (auf der App-Seite) und wieder zurück in latin_1 (auf der DB-Seite) konvertieren, aber es ist nur eine Illusion. Sie können sich durch die automatische Konvertierung der Datenbank in Ihre Spaltenkollatierung schleichen, indem Sie freetds verwenden und das Protokoll auf weniger als 7 setzen, aber Sie verlieren die Fähigkeit, nvarchar abzufragen.
Chugadie
1
@ Chugadie und Tevya: Diese Antwort ist ein bisschen unsinnig. SQL Server verwendet nur UCS-2 / UTF-16 zum Speichern von Unicode-Daten (dh XML- und 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.
Solomon Rutzky
2

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.

Chris Halcrow
quelle
1

Wenn Sie NVARCHARnur verwenden, weil eine gespeicherte Systemprozedur dies erfordert, wobei das häufigste Auftreten unerklärlich sp_executesqlist und Ihr dynamisches SQL sehr lang ist, sollten Sie aus Sicht der Leistung alle Zeichenfolgenmanipulationen (Verkettung, Ersetzung usw.) beim VARCHARKonvertieren durchführen das Endergebnis NVARCHARund füttere es in den proc-Parameter. Also nein, nicht immer benutzen NVARCHAR!

ajeh
quelle