Mit SQL Server 2019 führt Microsoft die UTF-8-Unterstützung für CHAR
und VARCHAR
Datentypen ein und sagt:
Diese Funktion kann je nach verwendetem Zeichensatz zu erheblichen Speichereinsparungen führen. Das Ändern eines vorhandenen Spaltendatentyps mit ASCII-Zeichenfolgen von NCHAR (10) in CHAR (10) unter Verwendung einer UTF-8-fähigen Sortierung führt beispielsweise zu einer Reduzierung des Speicherbedarfs um fast 50%. Diese Reduzierung ist darauf zurückzuführen, dass NCHAR (10) 22 Byte für die Speicherung benötigt, während CHAR (10) 12 Byte für dieselbe Unicode-Zeichenfolge benötigt.
UTF-8 scheint jedes Skript zu unterstützen , daher können wir grundsätzlich Unicode-Daten in varchar
und char
Spalten speichern . Und wie in der Dokumentation erwähnt, kann dies die Größe von Tabellen und Indizes verringern, und von dort aus können wir eine noch bessere Leistung erzielen, da weniger Daten gelesen werden.
Ich frage mich , bedeutet das wir aufhören kann zu verwenden nvarchar
und nchar
Spalten , die Geräte UTF-16?
Kann jemand ein Szenario und einen Grund UTF
angeben, die char-Datentypen nicht mit Codierung zu verwenden und weiterhin die n-chars- Datentypen zu verwenden?
CHAR
Typen schlechter als die Verwendung von Unicode-Typen (mit oder ohne Komprimierung, da Daten letztendlich nicht komprimiert werden müssen, um verarbeitet zu werden). Beachten Sie auch, dass der native Zeichenfolgentyp von Windows Unicode ist, sodass UTF-8-Zeichenfolgen häufig dekodiert werden müssen. Aufgrund der damit verbundenen Kompromisse ist es unwahrscheinlich, dass dieN
Typen bald in den Ruhestand versetzt werden.CHAR
ist wahrscheinlich SQL Server unter Linux, wenn die Engine native Unterstützung für die Verarbeitung von Zeichenfolgen direkt als UTF-8 erhält - hier ist UTF-8 der "native" Zeichensatz (mehr oder weniger) und das Beibehalten von Zeichenfolgen als UTF-16 ist die weniger effiziente Alternative. Es schadetCHAR
natürlich auch nicht, es unter Windows an Orten zu verwenden, an denen Sie es bereits verwenden , da Kollatierungen, die die Zeichen einschränken, die gespeichert werden können, nie attraktiv waren.Antworten:
Verringerung der Größe ist nur möglich , wenn die meisten der Charaktere im Wesentlichen sind
[space]
,0 - 9
,A - Z
,a - z
, und einige grundlegende Zeichensetzung. Außerhalb dieses bestimmten Zeichensatzes (in der Praxis Standard-ASCII-Werte 32 - 126) sind Sie bestenfalls gleich groß wieNVARCHAR
/ UTF-16 oder in vielen Fällen größer.Achtung. UTF-8 ist kein magischer "Alles reparieren" -Schalter. Wenn alle anderen Dinge gleich sind, verbessert weniger Lesen die Leistung. Aber hier sind "alle anderen Dinge" nicht gleich. Selbst wenn nur Standard-ASCII-Zeichen gespeichert werden (dh alle Zeichen sind 1 Byte groß und benötigen daher die Hälfte des Speicherplatzes im Vergleich zum Speichern in
NVARCHAR
), ist die Leistung von UTF-8 geringfügig beeinträchtigt. Ich glaube, das Problem ist darauf zurückzuführen, dass UTF-8 eine Codierung mit variabler Länge ist, was bedeutet, dass jedes Byte beim Lesen interpretiert werden muss, um zu wissen, ob es ein vollständiges Zeichen ist oder ob das nächste Byte ein Teil davon ist. Dies bedeutet, dass alle Zeichenfolgenoperationen am Anfang beginnen und byteweise fortgesetzt werden müssen. Auf der anderen Seite,NVARCHAR
/ UTF-16 besteht immer aus 2 Bytes (selbst Zusatzzeichen bestehen aus zwei 2-Byte-Codepunkten), sodass alles in 2-Byte-Blöcken gelesen werden kann.In meinen Tests hat das Speichern der Daten als UTF-8 selbst mit nur Standard-ASCII-Zeichen keine Zeitersparnis gebracht, war aber definitiv schlechter für die CPU-Zeit. Und das ohne Datenkomprimierung, sodass zumindest weniger Speicherplatz verwendet wurde. Bei Verwendung der Komprimierung war der für UTF-8 erforderliche Speicherplatz jedoch nur 1% - 1,5% kleiner. Also effektiv keine Platzersparnis noch höhere CPU-Zeit für UTF-8.
Bei der Verwendung
NVARCHAR(MAX)
wird es komplizierter, da die Unicode-Komprimierung mit diesem Datentyp nicht funktioniert, selbst wenn der Wert klein genug ist, um in einer Zeile gespeichert zu werden. Wenn die Daten jedoch klein genug sind, sollten sie dennoch von der Zeilen- oder Seitenkomprimierung profitieren (in diesem Fall werden sie tatsächlich schneller als UTF-8). Off-Row-Daten können jedoch keine Komprimierung verwenden.NVARCHAR(MAX)
Wenn Sie die Tabelle jedoch zu einem Clustered Columnstore-Index machen, wird die Größe von erheblich reduziert (auch wenn sie bei Verwendung des Clustered Columnstore-Index immer noch geringfügig größer als UTF-8 ist).Bestimmt. Tatsächlich finde ich in den meisten Fällen keinen zwingenden Grund, es zu verwenden. Das einzige Szenario, das wirklich von UTF-8 profitiert, ist:
VARCHAR
) verfügbar ist.Meine Tests haben gezeigt, dass NVARCHAR in fast allen Fällen schneller war, insbesondere wenn mehr Daten vorhanden waren. Tatsächlich benötigten 21.000 Zeilen mit durchschnittlich 5.000 Zeichen pro Zeile 165 MB für UTF-8 und 236 MB für
NVARCHAR
unkomprimierte Zeilen . Und doch war dasNVARCHAR
in der verstrichenen Zeit 2x schneller und in der CPU-Zeit mindestens 2x schneller (manchmal mehr). Trotzdem wurden 71 MB mehr auf der Festplatte benötigt.Abgesehen davon würde ich die Verwendung von UTF-8, zumindest ab CTP 2, aufgrund einer Vielzahl von Fehlern, die ich in dieser Funktion gefunden habe, immer noch nicht empfehlen.
Eine detaillierte Analyse dieser neuen Funktion, einschließlich einer Erläuterung der Unterschiede zwischen UTF-16 und UTF-8 sowie einer Auflistung dieser Fehler, finden Sie in meinem Beitrag:
Native UTF-8-Unterstützung in SQL Server 2019: Retter oder falscher Prophet?
quelle
Die UTF-8-Unterstützung bietet Ihnen eine Reihe neuer Optionen. Mögliche Platzersparnisse (ohne Zeilen- oder Seitenkomprimierung ) sind eine Überlegung, aber die Auswahl von Typ und Codierung sollte wahrscheinlich in erster Linie auf der Grundlage der tatsächlichen Anforderungen für Vergleich, Sortierung, Datenimport und -export erfolgen .
Möglicherweise müssen Sie mehr ändern, als Sie denken, da beispielsweise ein
nchar(1)
Typ zwei Byte Speicherplatz bereitstellt. Dies reicht aus, um ein beliebiges Zeichen in BMP zu speichern (Codepunkte 000000 bis 00FFFF). Einige der Zeichen in diesem Bereich würden in UTF-8 mit nur 1 Byte codiert, während andere 2 oder sogar 3 Bytes benötigen würden ( weitere Einzelheiten finden Sie in dieser Vergleichstabelle ). Daher wäre es erforderlich, sicherzustellen, dass derselbe Zeichensatz in UTF-8 abgedeckt wirdchar(3)
.Beispielsweise:
gibt den bekannten Fehler:
Oder wenn das Ablaufverfolgungsflag 460 aktiv ist:
Das Erweitern der UTF8-Spalte auf
char(2)
odervarchar(2)
behebt den Fehler fürNCHAR(911)
:Wenn dies jedoch z. B. der
NCHAR(8364)
Fall wäre, müssten Sie die Spalte weiter aufchar(3)
oder erweiternvarchar(3)
.Beachten Sie auch, dass die UTF-8-Kollatierungen alle zusätzliche Zeichen verwenden und daher nicht mit der Replikation funktionieren .
Abgesehen von allem anderen ist die UTF-8-Unterstützung derzeit nur in der Vorschau verfügbar und daher nicht für die Produktion verfügbar.
quelle