`Nvarchar / nchar` ne zaman SQL Server 2019 ile kullanılacaktır?


11

SQL Server 2019 Microsoft'un tanıtır ile UTF-8 desteği için CHARve VARCHARveri türleri ve der ki:

Bu özellik, kullanılan karakter kümesine bağlı olarak önemli miktarda depolama tasarrufu sağlayabilir. Örneğin, UTC-8 etkin bir harmanlama kullanarak ASCII dizeleri olan mevcut bir sütun veri türünün NCHAR (10) 'dan CHAR (10)' a değiştirilmesi, depolama gereksinimlerinde yaklaşık% 50 azalmaya dönüşür. Bu azalma, NCHAR'ın (10) depolanması için 22 bayta ihtiyaç duyması, CHAR'ın (10) aynı Unicode dizesi için 12 bayta ihtiyaç duymasıdır.

UTF-8 her komut dosyasını destekliyor gibi görünüyor , bu nedenle temel olarak Unicode verilerini varcharve charsütunlarında depolamaya başlayabiliriz . Belgelerde belirtildiği gibi, bu tabloların ve dizinlerin boyutunu azaltabilir ve oradan daha iyi performans elde edebiliriz, çünkü daha az miktarda veri okunur.

Acaba bu UTF-16 uygulayan nvarcharve ncharsütunları kullanmayı durdurabileceğimiz anlamına mı geliyor?

Char veri türlerini UTFkodlama ile kullanmamak ve n-chars olanları kullanmaya devam etmek değil, bir senaryoyu ve nedeni işaret edebilir mi?


Neden test edip rapor vermiyorsunuz? Ayrıca nvarchar'dan varchar'a dönüştürmek için ne kadar çaba harcadığınızı - değişiklik tablolarının ne kadar sürdüğünü ve test etmek için ne kadar zaman harcadığınızı ve hangi sorunlarla karşılaştığınızı bize bildirin.
Colin 't Hart

@ Colin'tHart Bilinen herhangi bir sorun veya husus yoksa, daha az veri okumanın sistem için daha iyi performans sağlayacağına inandığım için verileri taşımayı planlıyorum. Dönüşüm hakkında - tabii ki, özellikle verilen sütuna sahip dizinleriniz varsa - yeniden inşa edilmesi gerekiyor, ancak iyi ödeyeceğine inanıyorum. Tabii ki yakında performans etkisini test edeceğim, sadece göçü gereksiz kılacak sorunları arayacağım.
gotqn

SQL Server'ın PAGE veya ROW sıkıştırmasını kullanırken NVarchar sütunları için Unicode Sıkıştırma'yı desteklediğini unutmayın. docs.microsoft.com/tr-tr/sql/relational-databases/…
David Browne - Microsoft

1
UTF-8'in "ASCII benzeri verileri" saklıyorsanız yerden tasarruf edebilmesine rağmen, kendi başına sıkıştırma olmadığını ve bu şekilde karıştırılmaması gerektiğini belirtmek gerekir. Örneğin, bir veritabanında çoğunlukla Çince adları saklıyorsanız, UTF-8 CHARtürlerini Unicode türlerinden daha kötü kullanırsınız (sıkıştırma ile veya sıkıştırma olmadan, sonuçta verilerin işlenmesi için sıkıştırılmaması gerekir). Windows'un yerel dize türünün Unicode olduğunu da göz önünde bulundurun, bu nedenle UTF-8 dizelerinin deşifre edilmesi gerekir. Söz konusu tutarlar, Ntürlerin yakın bir zamanda kullanımdan kaldırılamayacağı anlamına gelir .
Jeroen Mostert

1
UTF-8 için # 1 "katil uygulaması" CHAR, motor dizeleri doğrudan UTF-8 olarak işlemek için yerel destek alırsa, muhtemelen Linux'ta SQL Server'dır - burada UTF-8, "yerel" karakter kümesidir (daha fazla veya daha az) ve dizeleri UTF-16 olarak tutmak daha az verimli bir alternatiftir. Tabii ki, Windows'ta zaten kullandığınız yerlerde kullanmak zarar vermez CHAR, çünkü saklanabilecek karakterleri kısıtlayan harmanlamalar hiç çekici olmamıştır.
Jeroen Mostert

Yanıtlar:


6

Bu olabilir tablolar ve dizinler boyutunu azaltmak (eklenen)

Eğer boyutunda Azaltma mümkündür çoğu karakter esasen vardır [space], 0 - 9, A - Z, a - z, ve bazı temel noktalama. Bu belirli karakter kümesinin dışında (pratik kullanım terimleriyle, standart ASCII değerleri 32 - 126), en iyi şekilde NVARCHAR/ UTF-16'ya eşit veya birçok durumda daha büyük olacaksınız .

Verileri daha az veri okumanın sistem için daha iyi performans sağlayacağına inandığım için verileri taşımayı planlıyorum.

Dikkatli ol. UTF-8 sihirli bir "her şeyi düzelt" anahtarı değildir. Tüm diğer şeyler eşit olmakla birlikte, evet, daha az okumak performansı artırır. Fakat burada "diğer her şey" eşit değildir . Yalnızca standart ASCII karakterleri saklarken bile (yani: tüm karakterler 1 bayttır, bu nedenle depolamaya kıyasla alanın yarısını gerektirir NVARCHAR), UTF-8'i kullanmak için hafif bir performans cezası vardır. Sorunun UTF-8'in değişken uzunluklu bir kodlama olmasından kaynaklandığına inanıyorum, yani her bir baytın tam bir karakter olup olmadığını veya bir sonraki baytın bir parçası olup olmadığını bilmek için okunması gerektiği şeklinde yorumlanması gerekir. Bu, tüm dize işlemlerinin başlangıçta başlaması ve bayt-byte-ilerlemesi gerektiği anlamına gelir. Diğer yandan,NVARCHAR / UTF-16 her zaman 2 bayttır (Tamamlayıcı Karakterler bile 2 baytlık Kod Noktalarından oluşur), bu nedenle her şey 2 baytlık parçalar halinde okunabilir.

Testlerimde, sadece standart ASCII karakterleri ile bile , verilerin UTF-8 olarak saklanması, geçen zamandan tasarruf sağlamaz, ancak CPU zamanı için kesinlikle daha kötüydü. Ve bu Veri Sıkıştırma olmadan, en azından daha az disk alanı vardı. Ancak, sıkıştırma kullanılırken UTF-8 için gereken alan sadece% 1 -% 1.5 daha azdı. Bu yüzden etkili bir şekilde yer tasarrufu yok ancak UTF-8 için daha yüksek CPU zamanı.

NVARCHAR(MAX)Değer satırda depolanacak kadar küçük olsa bile, Unicode Sıkıştırma bu veri türüyle çalışmadığından, işler kullanıldığında daha karmaşık hale gelir . Ancak, veriler yeterince küçükse, yine de Satır veya Sayfa Sıkıştırma'dan faydalanmalıdır (bu durumda aslında UTF-8'den daha hızlı olur). Ancak, sıra dışı veriler herhangi bir sıkıştırma kullanamaz. Yine de, tabloyu Kümelenmiş bir Columnstore Dizini yapmak büyük ölçüde küçültür NVARCHAR(MAX)(Kümelenmiş Columnstore Dizini kullanılırken UTF-8'den biraz daha büyük olsa bile).

Herhangi bir senaryoyu ve nedeni işaret edebilir, char veri türlerini UTF kodlamasıyla kullanamaz

Kesinlikle. Aslında, çoğu durumda kullanmak için gerçekten zorlayıcı bir neden bulamıyorum. UTF-8'den gerçekten yararlanan tek senaryo:

  1. Veriler çoğunlukla standart ASCII'dir (0 - 127 değerleri)
  2. Unicode olması gerekir, çünkü herhangi bir 8-bit Kod Sayfasında mevcut olandan daha geniş bir karakter aralığı depolaması gerekebilir (örn. VARCHAR)
  3. Verilerin çoğu çevrimdışı olarak depolanır (bu nedenle Sayfa sıkıştırma özelliği çalışmaz)
  4. Sorgulama yapmayan performans nedenleriyle boyutu düşürmek için ihtiyaç duyduğunuz / istediğiniz yeterli veriye sahipsiniz (örn. Yedekleme boyutunu azaltın, yedekleme / geri yükleme için gereken süreyi azaltın, vb.)
  5. Kümelenmiş Sütun Dizini'ni kullanamazsınız (belki de tablonun kullanımı bu durumda performansı daha da kötüleştirir?)

Testlerim neredeyse tüm durumlarda NVARCHAR'ın, özellikle de daha fazla veri olduğunda daha hızlı olduğunu gösteriyor. Aslında, satır başına ortalama 5 bin karakter içeren 21 bin satır UTF-8 için 165 MB ve NVARCHARsıkıştırılmamış için 236 MB gerektirir . Yine de NVARCHARgeçen sürede 2 kat daha hızlı ve CPU zamanında en az 2 kat daha hızlıydı (bazen daha fazla). Yine de, diskte 71 MB daha fazla yer kapladı.

Bunun dışında, bu özellikte bulduğum çeşitli hatalar nedeniyle hala en azından CTP 2'den itibaren UTF-8 kullanmanızı tavsiye etmem.

UTF-16 ve UTF-8 arasındaki farkların açıklaması ve bu hataların bir listesi de dahil olmak üzere bu yeni özelliğin ayrıntılı bir analizi için lütfen yazıma bakın:

SQL Server 2019'da Yerel UTF-8 Desteği: Kurtarıcı mı yoksa Sahte Peygamber?


12

UTF-8 desteği size yeni seçenekler sunar. Potansiyel alan tasarrufu ( satır veya sayfa sıkıştırması olmadan ) bir husustur, ancak tür ve kodlama seçimi büyük olasılıkla karşılaştırma, sıralama, veri içe aktarma ve dışa aktarma için gerçek gereksinimler temelinde yapılmalıdır .

Örneğin bir nchar(1)tür iki bayt depolama alanı sağladığından , düşündüğünüzden daha fazlasını değiştirmeniz gerekebilir . Bu, herhangi bir karakter depolamak için yeterli BMP (kod noktaları 00ffff 000000). Bu aralıktaki karakterlerin bazıları UTF-8'de sadece 1 bayt ile kodlanırken, diğerleri 2 veya hatta 3 bayt gerektirir ( daha fazla ayrıntı için bu karşılaştırma tablosuna bakın). Bu nedenle, UTF-8'de aynı karakter kümesinin kapsamının sağlanması gerekir char(3).

Örneğin:

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

tanıdık hata veriyor:

Msg 8152, Seviye 16, Durum 30, Satır xxx
Dize veya ikili veriler kesilir.

Veya izleme bayrağı 460 etkinse:

Msg 2628, Seviye 16, Durum 1, Satır xxx
Dize veya ikili veriler, '@T' tablosunda, 'UTF8' sütununda kesilir. Kesik değer: ''.

UTF8 sütununu genişletmek char(2)veya varchar(2)şu hatayı giderir 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);

Ancak, örneğin NCHAR(8364), sütunu char(3)veya değerine daha da genişletmeniz gerekir varchar(3).

Ayrıca UTF-8 harmanlamalarının tamamlayıcı karakterler kullandığını unutmayın, bu nedenle çoğaltma ile çalışmaz .

Başka bir şey dışında, UTF-8 desteği şu anda yalnızca önizleme içindedir, bu nedenle üretim kullanımı için mevcut değildir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.