Wann wird "nvarchar / nchar" mit SQL Server 2019 verwendet?

11

Mit SQL Server 2019 führt Microsoft die UTF-8-Unterstützung für CHARund VARCHARDatentypen 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 varcharund charSpalten 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 nvarcharund ncharSpalten , die Geräte UTF-16?

Kann jemand ein Szenario und einen Grund UTFangeben, die char-Datentypen nicht mit Codierung zu verwenden und weiterhin die n-chars- Datentypen zu verwenden?

gotqn
quelle
Warum testest du es nicht und meldest dich zurück? Lassen Sie uns auch wissen, wie viel Aufwand Sie für die Konvertierung von nvarchar in varchar aufgewendet haben - wie lange die Änderungstabellen gedauert haben, wie viel Zeit Sie mit dem Testen verbracht haben und auf welche Probleme Sie gestoßen sind.
Colin 't Hart
@ Colin'tHart Wenn keine Probleme oder Überlegungen bekannt sind, plane ich, die Daten zu migrieren, da ich glaube, dass das Lesen von weniger Daten zu einer besseren Leistung des Systems führt. Über die Konvertierung - es wird natürlich einige Zeit dauern, insbesondere wenn Sie Indizes mit der angegebenen Spalte haben - müssen sie neu erstellt werden, aber ich glaube, dass es sich gut auszahlt. Natürlich werde ich bald die Auswirkungen auf die Leistung testen und nur nach Problemen suchen, die die Migration unnötig machen.
Gotqn
Beachten Sie, dass SQL Server die Unicode-Komprimierung für NVarchar-Spalten unterstützt, wenn die PAGE- oder ROW-Komprimierung verwendet wird. docs.microsoft.com/en-us/sql/relational-databases/…
David Browne - Microsoft
1
Es ist erwähnenswert, dass UTF-8 zwar Speicherplatz spart, wenn Sie "ASCII-ähnliche Daten" speichern, jedoch keine Komprimierung an sich darstellt und nicht als solche verwechselt werden sollte. Wenn Sie beispielsweise hauptsächlich chinesische Namen in einer Datenbank speichern, ist die Verwendung von UTF-8- CHARTypen 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 die NTypen bald in den Ruhestand versetzt werden.
Jeroen Mostert
1
Die "Killer-App" Nr. 1 für UTF-8 CHARist 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 schadet CHARnatü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.
Jeroen Mostert

Antworten:

6

Dies kann die Größe von Tabellen und Indizes verringern (Hervorhebung hinzugefügt).

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ß wie NVARCHAR/ UTF-16 oder in vielen Fällen größer.

Ich plane, die Daten zu migrieren, da ich glaube, dass das Lesen von weniger Daten zu einer besseren Leistung des Systems führen wird.

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

Kann jemand ein Szenario und einen Grund angeben, die char-Datentypen nicht mit UTF-Codierung zu verwenden

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:

  1. Daten sind meistens Standard-ASCII (Werte 0 - 127)
  2. Es muss Unicode sein, da möglicherweise ein größerer Zeichenbereich gespeichert werden muss, als auf einer einzelnen 8-Bit-Codepage (dh VARCHAR) verfügbar ist.
  3. Die meisten Daten werden außerhalb der Zeile gespeichert (sodass die Seitenkomprimierung nicht einmal funktioniert).
  4. Sie verfügen über genügend Daten, die Sie aus Gründen der Nichtabfrageleistung benötigen / reduzieren möchten (z. B. Sicherungsgröße reduzieren, Zeit für Sicherung / Wiederherstellung reduzieren usw.).
  5. Sie können den Clustered Columnstore Index nicht verwenden (möglicherweise verschlechtert die Verwendung der Tabelle in diesem Fall die Leistung?)

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 NVARCHARunkomprimierte Zeilen . Und doch war das NVARCHARin 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?

Solomon Rutzky
quelle
12

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 wird char(3).

Beispielsweise:

DECLARE @T AS table 
(
    n integer PRIMARY KEY,
    UTF16 nchar(1) COLLATE Latin1_General_CI_AS,
    UTF8 char(1) COLLATE Latin1_General_100_CI_AS_SC_UTF8
);

INSERT @T (n, UTF16, UTF8)
SELECT 911, NCHAR(911), NCHAR(911);

gibt den bekannten Fehler:

Nachricht 8152, Ebene 16, Status 30, Zeile xxx
Zeichenfolge oder Binärdaten werden abgeschnitten.

Oder wenn das Ablaufverfolgungsflag 460 aktiv ist:

Nachricht 2628, Ebene 16,
Status 1, Zeile xxx Zeichenfolge oder Binärdaten werden in Tabelle '@T', Spalte 'UTF8' abgeschnitten. Abgeschnittener Wert: ''.

Das Erweitern der UTF8-Spalte auf char(2)oder varchar(2)behebt den Fehler für NCHAR(911):

DECLARE @T AS table 
(
    n integer PRIMARY KEY,
    UTF16 nchar(1) COLLATE Latin1_General_CI_AS,
    UTF8 varchar(2) COLLATE Latin1_General_100_CI_AS_SC_UTF8
);

INSERT @T (n, UTF16, UTF8)
SELECT 911, NCHAR(911), NCHAR(911);

Wenn dies jedoch z. B. der NCHAR(8364)Fall wäre, müssten Sie die Spalte weiter auf char(3)oder erweitern varchar(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.

Paul White 9
quelle