Z Microsoft SQL Server 2019 wprowadza UTF-8 za CHAR
i VARCHAR
typów danych i mówi:
Ta funkcja może zapewnić znaczne oszczędności pamięci, w zależności od używanego zestawu znaków. Na przykład zmiana istniejącego typu danych kolumny za pomocą ciągów ASCII z NCHAR (10) na CHAR (10) przy użyciu sortowania z włączoną funkcją UTF-8 przekłada się na prawie 50% zmniejszenie wymagań dotyczących pamięci. Zmniejszenie to wynika z tego, że NCHAR (10) wymaga 22 bajtów do przechowywania, podczas gdy CHAR (10) wymaga 12 bajtów dla tego samego ciągu Unicode.
Wydaje się, że UTF-8 obsługuje każdy skrypt, więc w zasadzie możemy zacząć przechowywać dane varchar
i char
kolumny Unicode . I jak powiedziano w dokumentacji, może to zmniejszyć rozmiar tabel i indeksów, a stamtąd możemy uzyskać jeszcze lepszą wydajność, ponieważ odczytywana jest mniejsza ilość danych.
Zastanawiam się, czy to oznacza, że możemy przestać używać nvarchar
i nchar
kolumn, które implementują UTF-16?
Czy ktoś może wskazać scenariusz i powód, aby nie używać typów danych char z UTF
kodowaniem i nadal używać n-znaków?
CHAR
typów UTF-8 niż typów Unicode (z kompresją lub bez, ponieważ ostatecznie dane muszą zostać rozpakowane do przetworzenia). Weź również pod uwagę, że rodzimym typem ciągów Windows jest Unicode, więc ciągi UTF-8 często wymagają dekodowania. Związane z tym kompromisy oznaczają, żeN
typy nie zostaną wkrótce wycofane.CHAR
jest prawdopodobnie SQL Server w systemie Linux, jeśli silnik otrzymuje natywną obsługę przetwarzania ciągów znaków bezpośrednio jako UTF-8 - tutaj UTF-8 jest „rodzimym” zestawem znaków (mniej więcej) i utrzymywanie ciągów w pobliżu, ponieważ UTF-16 jest mniej wydajną alternatywą. Oczywiście nie zaszkodzi również używać go w systemie Windows w miejscach, w których już używaszCHAR
, ponieważ układanie ograniczające znaki, które można przechowywać, nigdy nie było atrakcyjne.Odpowiedzi:
Zmniejszenie rozmiaru to tylko możliwe, jeśli większość z bohaterów są w istocie
[space]
,0 - 9
,A - Z
,a - z
, a niektóre podstawowe znaki interpunkcyjne. Poza tym konkretnym zestawem znaków (w praktyce, standardowe wartości ASCII 32–126) będziesz w najlepszym razie równy rozmiarowiNVARCHAR
/ UTF-16, lub w wielu przypadkach większy.Bądź ostrożny. UTF-8 nie jest magicznym przełącznikiem „napraw wszystko”. Wszystkie inne rzeczy są równe, tak, czytanie mniej poprawia wydajność. Ale tutaj „wszystkie inne rzeczy” nie są równe. Nawet przy przechowywaniu tylko standardowych znaków ASCII (co oznacza, że wszystkie znaki mają 1 bajt, a zatem wymagają połowy miejsca w porównaniu do przechowywania w
NVARCHAR
), istnieje niewielka utrata wydajności za użycie UTF-8. Uważam, że problem wynika z faktu, że UTF-8 jest kodowaniem o zmiennej długości, co oznacza, że każdy bajt musi być interpretowany podczas odczytu, aby wiedzieć, czy jest to pełny znak, czy też następny bajt jest jego częścią. Oznacza to, że wszystkie operacje na łańcuchach muszą zaczynać się od początku i następować bajt po bajcie. Z drugiej strony,NVARCHAR
/ UTF-16 ma zawsze 2 bajty (nawet znaki uzupełniające składają się z dwóch 2-bajtowych punktów kodowych), więc wszystko można odczytać w 2-bajtowych porcjach.W moich testów, nawet z tylko standardowych znaków ASCII, przechowującego dane jako UTF-8 Nie umieszczono oszczędności upływającego czasu, ale był zdecydowanie gorszy dla czasu procesora. I to bez kompresji danych, więc przynajmniej było mniej miejsca na dysku. Ale podczas korzystania z kompresji przestrzeń wymagana dla UTF-8 była tylko 1% - 1,5% mniejsza. Tak więc efektywnie brak oszczędności miejsca i jeszcze dłuższy czas procesora dla UTF-8.
Sprawa się komplikuje, gdy używasz,
NVARCHAR(MAX)
ponieważ kompresja Unicode nie działa z tym typem danych, nawet jeśli wartość jest na tyle mała, że można ją przechowywać w wierszu. Ale jeśli dane są wystarczająco małe, nadal powinny korzystać z kompresji wierszy lub stron (w takim przypadku faktycznie stają się one szybsze niż UTF-8). Jednak dane poza wierszem nie mogą korzystać z żadnej kompresji. Nadal jednak uczynienie z tabeli Indeks klastrowego magazynu kolumn znacznie zmniejsza rozmiarNVARCHAR(MAX)
(nawet jeśli nadal jest on nieco większy niż UTF-8 przy użyciu Indeks klastrowanego magazynu kolumn).Zdecydowanie. W rzeczywistości nie znajduję przekonującego powodu, aby z niego korzystać w większości przypadków. Jedyny scenariusz, który naprawdę korzysta z UTF-8, to:
VARCHAR
)Moje testy pokazują, że w prawie wszystkich przypadkach NVARCHAR był szybszy, szczególnie gdy było więcej danych. W rzeczywistości 21 tys. Wierszy ze średnio 5 tys. Znaków na wiersz wymagało 165 MB dla UTF-8 i 236 MB dla
NVARCHAR
nieskompresowanych. A jednakNVARCHAR
był dwa razy szybszy w czasie, który upłynął, i co najmniej 2x szybszy (czasem więcej) w czasie procesora. Mimo to zajęło 71 MB więcej na dysku.Poza tym nadal nie zalecałbym używania UTF-8, przynajmniej od CTP 2, z powodu różnych błędów, które znalazłem w tej funkcji.
Aby uzyskać szczegółową analizę tej nowej funkcji, w tym wyjaśnienie różnic między UTF-16 i UTF-8, oraz listę tych błędów, zobacz mój post:
Natywne wsparcie UTF-8 w SQL Server 2019: Zbawiciel czy fałszywy prorok?
źródło
Obsługa UTF-8 daje nowy zestaw opcji. Potencjalne oszczędności miejsca (bez kompresji wierszy lub strony ) to jedna kwestia, ale wybór rodzaju i kodowania powinien być prawdopodobnie dokonywany przede wszystkim na podstawie rzeczywistych wymagań dotyczących porównania, sortowania, importu i eksportu danych .
Być może będziesz musiał zmienić więcej, niż myślisz, ponieważ np.
nchar(1)
Typ zapewnia dwa bajty pamięci. To wystarczy, aby zapisać dowolny znak w BMP (punkty kodowe od 000000 do 00FFFF). Niektóre znaki z tego zakresu byłyby kodowane za pomocą 1 bajtu w UTF-8, podczas gdy inne wymagałyby 2 lub nawet 3 bajtów ( więcej szczegółów zawiera ta tabela porównawcza ). Dlatego wymagałoby to pokrycia tego samego zestawu znaków w UTF-8char(3)
.Na przykład:
daje znany błąd:
Lub jeśli flaga śledzenia 460 jest aktywna:
Rozszerzenie kolumny UTF8 do
char(2)
lubvarchar(2)
rozwiązuje błąd dlaNCHAR(911)
:Jednak gdyby tak było np.
NCHAR(8364)
, Konieczne byłoby dalsze rozwinięcie kolumny, dochar(3)
lubvarchar(3)
.Zauważ również, że wszystkie sortowania UTF-8 używają znaków dodatkowych, więc nie będą działać z replikacją.
Oprócz czegokolwiek innego, obsługa UTF-8 jest obecnie tylko w wersji zapoznawczej, więc nie jest dostępna do użytku produkcyjnego.
źródło