Jaka jest różnica między varchar a nvarchar?

1354

Czy to tylko nvarcharobsługuje znaki wielobajtowe? Jeśli tak jest, to czy rzeczywiście jest coś innego niż problemy z przechowywaniem varchars?

stymuluje
źródło
6
Lubię punkt incomudro, to właśnie doprowadziło mnie do rozejrzenia się na temat różnicy między varchar i nvarchar. Nasza aplikacja Java dla bazy danych SQL Server używa myBatis, który domyślnie wydaje ciągi jako nvarchar (wciąż nie jestem pewien, w jaki sposób (lub jeśli) to można zastąpić). Proste zapytanie pokazywało się jako ogromny problem z wydajnością, ponieważ zdefiniowałem wybraną kolumnę jako varchar, a nie nvarchar, i ignorowałem indeks w kolumnie.
Sean

Odpowiedzi:

1652

nvarcharKolumna może przechowywać żadnych danych Unicode. varcharKolumna jest ograniczony do 8-bitowych kodowej. Niektórzy uważają, że varcharnależy tego użyć, ponieważ zajmuje mniej miejsca. Uważam, że to nie jest poprawna odpowiedź. Niezgodności strony kodowej są uciążliwe, a Unicode jest lekarstwem na problemy ze stroną kodową. W dzisiejszych czasach przy niskim koszcie dysku i pamięci naprawdę nie ma powodu, aby marnować czas na przeszukiwanie stron kodowych.

Wszystkie nowoczesne systemy operacyjne i platformy programistyczne wykorzystują wewnętrznie Unicode. Używając nvarcharzamiast varchar, możesz uniknąć konwersji kodowania za każdym razem, gdy czytasz lub zapisujesz w bazie danych. Konwersje wymagają czasu i są podatne na błędy. Odzyskiwanie po błędach konwersji jest nietrywialnym problemem.

Jeśli łączysz się z aplikacją korzystającą tylko z ASCII, nadal zalecałbym użycie Unicode w bazie danych. Algorytmy sortowania systemu operacyjnego i bazy danych będą działać lepiej z Unicode. Unicode pozwala uniknąć problemów z konwersją podczas łączenia z innymi systemami. I będziesz się przygotowywał na przyszłość. I zawsze możesz potwierdzić, że Twoje dane są ograniczone do 7-bitowego ASCII dla dowolnego starszego systemu, który musisz utrzymywać, nawet korzystając z niektórych zalet pełnej pamięci Unicode.

Jeffrey L. Whitledge
źródło
8
To jest wspaniała informacja. Czy zatem rozumiem to poprawnie, jeśli wywnioskuję, że wybór ostatecznie staje się jednym z - który zasób jest tańszy: obciążenie procesorem + programowanie czy pamięć?
Matt Cashatt
141
@MatthewPatrickCashatt - Możesz to zobaczyć w ten sposób. Ale jeśli wyobrażasz sobie wspaniały świat, w którym wszystkie dane tekstowe są w formacie Unicode, a programiści po prostu nigdy nie muszą myśleć o tym, w czym coś jest kodowane, a cała klasa błędów po prostu nigdy się nie pojawia, możesz zauważyć, że jest naprawdę nie ma wyboru.
Jeffrey L. Whitledge
8
@Martin Smith - W tych przypadkach zniknęła niewielka zaleta, jaką zapewnia varchar (kompaktowe przechowywanie). Myślę, że Varchar jest jeszcze gorszy niż myślałem!
Jeffrey L Whitledge
9
@PeterAllenWebb - Możesz „przechowywać” dowolne dane Unicode, ponieważ pary zastępcze w UTF-16 mogą być przechowywane w UCS-2 tak, jakby były znakami. Będzie to działało transparentnie w przypadku przechowywania i wyszukiwania danych. Teraz nie możesz uzyskać wiarygodnych przekształceń przypadków i porównań poza BMP, ale nie twierdziłem o tym. Więc jeśli masz dużo tekstu Desseret, na którym chcesz przetwarzać, najlepiej byłoby to zrobić poza bazą danych. Ale dobrze jest tam przechowywać. (Oczywiście,
Varchar też
259

varchar : Dane znakowe o zmiennej długości, inne niż Unicode. Zestawienie bazy danych określa, na której stronie kodowej przechowywane są dane.

nvarchar : Dane znakowe o zmiennej długości Unicode. W zależności od zestawienia bazy danych do porównań.

Uzbrojony w tę wiedzę, użyj dowolnego, który pasuje do twoich danych wejściowych (ASCII v. Unicode).

użytkownik7116
źródło
5
Czy istnieje ograniczenie takie jak varchar nie może przechowywać danych Unicode? Wszystkie 1 i 0. Jestem w stanie zapisać chińskie treści jako varchar w porządku dla mojej bazy danych. Podaję tylko jego UTF-8. Jak to działa?
Nishant
3
@Nishant późna odpowiedź : oczywiście możesz przechowywać UTF-8 w varchar, ale spowoduje to przerwanie funkcji ciągów SQL Server. Jeśli wykonasz wszystkie wyszukiwania / przekształcenia w swojej aplikacji, to tak, możesz to zrobić (ale jaka jest korzyść?). Tylko kodowanie Unicode obsługiwane przez SS to UCS-2 (tak, nie UTF-16 przed SS2k16), a jego funkcje łańcuchowe działają tylko z tym kodowaniem. BTW co z indeksami? Jeśli chcesz przechowywać dowolne dane, lepiej zamiast tego użyj pliku binarnego.
Adriano Repetti,
Tak, po prostu psuje funkcje wyszukiwania ciągów.
Nishant,
8
Więc wiesz ... to nie działa. To jak przechowywanie floatw produkt inti odchodzą, „dobrze, czy dziesiętne iść brakuje.” Po prostu nie.
user7116,
70

Zawsze używam nvarchar, ponieważ pozwala temu, co buduję, wytrzymać prawie wszystkie dane, które do niego rzucam. Mój system CMS robi przypadkowo chiński, ponieważ użyłem nvarchar. Obecnie żadne nowe aplikacje nie powinny tak naprawdę zajmować się wymaganą ilością miejsca.

tags2k
źródło
25
Pomysł, że nowe aplikacje nie powinny zajmować się ograniczeniami przestrzeni, jest nieco krótkowzroczny, a każdy, kto miał do czynienia z bazami danych na poziomie średnim lub dużym, z przyjemnością Ci powie, zupełnie niepoprawnie.
Brat
60
Aby móc swobodnie umieszczać słowa w ustach tag2k, myślę, że bardziej trafnym stwierdzeniem może być: „jest coraz bardziej mało prawdopodobne, aby jakiekolwiek nowe aplikacje bardziej przejmowały się wymaganą przestrzenią niż internacjonalizacją i innymi problemami związanymi z zestawem znaków”.
Cowan
1
„W dzisiejszych czasach żadne nowe aplikacje nie powinny tak naprawdę zajmować się wymaganą ilością miejsca”. - O ile nie korzystasz z bezpłatnego miejsca w chmurze, gdzie płatny abonament jest ROZWAŻNY skokiem w $ (zobacz wspólne plany AppHarbor SQL Server).
ganders
3
@ganders Howl! Jesteś tam Instrukcje uogólnione są w najlepszym razie tylko tymczasowo poprawne. Komputery to zdecydowanie gra typu swing i rondo. Jestem zdecydowanie zaniepokojony tym, ile miejsca używam na Windows Azure CCP. To powiedziawszy, że „nigdy” nie użyję varchar zamiast nvarchar. Ooo, czy po prostu zaprzeczałem sobie?
rism
1
@rism, uważam, że usunąłeś wszelkie ryzyko sprzeczności z użyciem cytatów "never", przynajmniej technicznie.
Smandoli,
30

To zależy od sposobu zainstalowania Oracle. Podczas procesu instalacji ustawiona jest opcja NLS_CHARACTERSET. Możesz go znaleźć za pomocą zapytania SELECT value$ FROM sys.props$ WHERE name = 'NLS_CHARACTERSET'.

Jeśli twój NLS_CHARACTERSET jest kodowaniem Unicode, takim jak UTF8, to świetnie. Korzystanie z VARCHAR i NVARCHAR jest prawie identyczne. Przestań czytać teraz, po prostu idź. W przeciwnym razie lub jeśli nie masz kontroli nad zestawem znaków Oracle, czytaj dalej.

VARCHAR - Dane są przechowywane w kodowaniu NLS_CHARACTERSET. Jeśli na tym samym serwerze znajdują się inne instancje bazy danych, mogą one być przez nich ograniczone; i vice versa, ponieważ musisz udostępnić ustawienie. W takim polu można przechowywać dowolne dane, które można zakodować przy użyciu tego zestawu znaków i nic więcej . Na przykład, jeśli zestaw znaków to MS-1252, możesz przechowywać tylko takie znaki, jak litery angielskie, garść liter akcentowanych i kilka innych (np. € i -). Twoja aplikacja przydałaby się tylko w kilku lokalizacjach, nie mogąc działać nigdzie indziej na świecie. Z tego powodu jest uważany za zły pomysł.

NVARCHAR - Dane są przechowywane w kodowaniu Unicode. Obsługiwany jest każdy język. Dobry pomysł.

Co z miejscem do przechowywania? VARCHAR jest ogólnie wydajny, ponieważ zestaw znaków / kodowanie zostało zaprojektowane specjalnie dla określonych ustawień regionalnych. Pola NVARCHAR przechowują albo w kodowaniu UTF-8, albo UTF-16, wystarczająco ironicznie opierając się na ustawieniach NLS. UTF-8 jest bardzo wydajny dla języków „zachodnich”, a jednocześnie obsługuje języki azjatyckie. UTF-16 jest bardzo wydajny dla języków azjatyckich, a jednocześnie obsługuje języki „zachodnie”. Jeśli martwisz się o przestrzeń dyskową, wybierz ustawienie NLS, aby Oracle stosował odpowiednio UTF-8 lub UTF-16.

Co z prędkością przetwarzania? Większość nowych platform kodowania używa natywnie kodu Unicode (Java, .NET, a nawet C ++ std :: wstring sprzed lat!), Więc jeśli pole bazy danych to VARCHAR, zmusza Oracle do konwersji między zestawami znaków przy każdym czytaniu lub zapisie, co nie jest zbyt dobre. Użycie NVARCHAR pozwala uniknąć konwersji.

Konkluzja: użyj NVARCHAR! Pozwala to uniknąć ograniczeń i zależności, świetnie nadaje się do przestrzeni dyskowej, a zwykle także do wydajności.

Jeremy Frank
źródło
42
To naprawdę dobra odpowiedź, z wyjątkiem tego, że pytanie dotyczy serwera SQL.
pobudza
21

nvarchar przechowuje dane jako Unicode, więc jeśli zamierzasz przechowywać dane wielojęzyczne (więcej niż jeden język) w kolumnie danych, potrzebujesz wariantu N.

albertein
źródło
16

Moje dwa centy

  1. Indeksy mogą się nie powieść, gdy nie zostaną użyte poprawne typy danych:
    W SQL Server: Gdy masz indeks nad kolumną VARCHAR i wyświetlasz ciąg Unicode, SQL Server nie korzysta z tego indeksu. To samo dzieje się, gdy prezentujesz BigInt w indeksowanej kolumnie zawierającej SmallInt. Nawet jeśli BigInt jest wystarczająco mały, aby być SmallInt, SQL Server nie może korzystać z indeksu. W drugą stronę nie masz tego problemu (podczas dostarczania SmallInt lub Ansi-Code do indeksowanej kolumny BigInt ot NVARCHAR).

  2. Typy danych mogą się różnić w zależności od systemu DBMS (DataBase Management System):
    wiedz, że każda baza danych ma nieco inne typy danych, a VARCHAR nie oznacza wszędzie tego samego. Podczas gdy SQL Server ma VARCHAR i NVARCHAR, baza danych Apache / Derby ma tylko VARCHAR, a tam VARCHAR jest w standardzie Unicode.

incomudro
źródło
Ale z pewnością, jeśli piszesz kod poprawnie (tj. Używając sparametryzowanych zapytań itp.), To punkt 1 jest mniej ryzykowny.
Paul
14

Głównie nvarchar przechowuje znaki Unicode, a varchar przechowuje znaki inne niż Unicode.

„Unicodes” oznacza 16-bitowy schemat kodowania znaków, umożliwiający kodowanie znaków z wielu innych języków, takich jak arabski, hebrajski, chiński, japoński, w jednym zestawie znaków.

Oznacza to, że Unicode używa 2 bajtów na znak do przechowywania, a nonunicodes używa tylko jednego bajtu na znak do przechowywania. Co oznacza, że ​​unicody wymagają podwójnej pojemności do przechowywania w porównaniu do unicodów.

ranjit pawar
źródło
10

Masz rację. nvarcharprzechowuje dane Unicode, a varcharprzechowuje dane znaków jednobajtowych. Inne niż różnic magazynowych ( nvarcharwymaga dwa razy więcej miejsca do przechowywania, jak varchar), który już wspomniano, głównym powodem, dla preferujących nvarcharponad varcharbyłoby internacjonalizacji (tj przechowywania łańcuchów w innych językach).

Mike Spross
źródło
10

Powiedziałbym, że to zależy.

Jeśli opracujesz aplikację komputerową, w której system operacyjny działa w standardzie Unicode (podobnie jak wszystkie obecne systemy Windows), a język natywnie obsługuje Unicode (domyślne łańcuchy to Unicode, jak w Javie lub C #), to przejdź do nvarchar.

Jeśli tworzysz aplikację internetową, w której ciągi znaków mają postać UTF-8, a językiem jest PHP, który nadal nie obsługuje natywnie kodu Unicode (w wersjach 5.x), prawdopodobnie varchar będzie prawdopodobnie lepszym wyborem.

sleepy012
źródło
9

Chociaż NVARCHARprzechowuje Unicode, powinieneś rozważyć przy pomocy sortowania, abyś mógł używać VARCHARi zapisywać dane w lokalnych językach.

Wyobraź sobie następujący scenariusz.

Zestawienie twojego DB jest perskie i zapisujesz wartość typu „علی” (perskie pisanie Ali) w VARCHAR(10)typie danych. Nie ma problemu, a DBMS używa tylko trzech bajtów do przechowywania.

Jeśli jednak chcesz przenieść swoje dane do innej bazy danych i zobaczyć poprawny wynik, docelowa baza danych musi mieć takie samo zestawienie jak cel, który w tym przykładzie jest perski.

Jeśli docelowe sortowanie jest inne, w docelowej bazie danych pojawiają się znaki zapytania (?).

Na koniec pamiętaj, jeśli korzystasz z ogromnej bazy danych, która jest przeznaczona do używania twojego lokalnego języka, zaleciłbym użycie lokalizacji zamiast zbyt dużej ilości spacji.

Wierzę, że projekt może być inny. To zależy od środowiska, w którym pracujesz.

Ali Elmi
źródło
8

Musiałem spojrzeć na odpowiedzi, a wiele z nich wydaje się polecić do korzystania nvarcharw ciągu varchar, ponieważ przestrzeń nie jest już problemem, więc nie ma nic złego w umożliwieniu Unicode dla małego dodatkowego miejsca. Nie zawsze jest to prawdą, gdy chcesz zastosować indeks do kolumny. SQL Server ma limit 900 bajtów wielkości pola, które można indeksować. Więc jeśli masz varchar(900), nadal możesz go indeksować, ale nie varchar(901). Za nvarcharpomocą liczba znaków jest zmniejszona o połowę, dzięki czemu można indeksować maksymalnie nvarchar(450). Więc jeśli masz pewność, że nie potrzebujesz nvarchar, nie polecam go używać.

Ogólnie rzecz biorąc, w bazach danych zalecam trzymanie się wymaganego rozmiaru, ponieważ zawsze możesz się rozwijać. Na przykład kolega w pracy pomyślał kiedyś, że korzystanie nvarchar(max)z kolumny nie jest szkodliwe , ponieważ w ogóle nie mamy problemu z przechowywaniem. Później, kiedy próbowaliśmy zastosować indeks do tej kolumny, SQL Server to odrzucił. Gdyby jednak zaczął od nawet varchar(5), moglibyśmy po prostu rozszerzyć go później na to, czego potrzebujemy, bez takiego problemu, który wymagałby od nas wykonania planu migracji w terenie w celu rozwiązania tego problemu.

Rafid
źródło
7

nVarchar pomoże ci przechowywać znaki Unicode. Jest to odpowiedni sposób, jeśli chcesz przechowywać zlokalizowane dane.

Vijesh VP
źródło
7

Jeśli do przechowywania znaku używany jest jeden bajt, istnieje 256 możliwych kombinacji, dzięki czemu można zapisać 256 różnych znaków. Sortowanie to wzór, który określa postacie i zasady, według których są one porównywane i sortowane.

1252, czyli Latin1 (ANSI), jest najczęstszy. Jednobajtowe zestawy znaków są również nieodpowiednie do przechowywania wszystkich znaków używanych w wielu językach. Na przykład niektóre języki azjatyckie mają tysiące znaków, więc muszą używać dwóch bajtów na znak.

Standard Unicode

Gdy systemy wykorzystujące wiele stron kodowych są używane w sieci, zarządzanie komunikacją staje się trudne. W celu standaryzacji konsorcjum ISO i Unicode wprowadziło Unicode . Unicode używa dwóch bajtów do przechowywania każdego znaku. Oznacza to, że można zdefiniować 65 536 różnych znaków, więc prawie wszystkie znaki można pokryć Unicode. Jeśli dwa komputery używają Unicode, każdy symbol będzie reprezentowany w ten sam sposób i nie jest wymagana konwersja - taka jest idea Unicode.

SQL Server ma dwie kategorie typów danych znakowych:

  • inny niż Unicode (char, varchar i tekst)
  • Unicode (nchar, nvarchar i ntext)

Jeśli musimy zapisać dane o postaci z wielu krajów, zawsze używaj Unicode.

Jithin Shaji
źródło
6

Muszę powiedzieć tutaj (zdaję sobie sprawę, że prawdopodobnie zamierzam otworzyć się na listwę!), Ale z pewnością jedyny moment, kiedy NVARCHARjest bardziej przydatny (zauważ, że jest tam więcej !) Niż VARCHARwtedy, gdy wszystkie zestawienia na wszystkich systemów zależnych i samej bazy danych są takie same ...? Jeśli nie, to i tak musi nastąpić konwersja zestawiania, co czyni VARCHARtak samo realnym jak NVARCHAR.

Aby dodać do tego, niektóre systemy baz danych, takie jak SQL Server (przed 2012 rokiem), mają rozmiar strony około. 8 tys. Tak więc, jeśli szukasz przechowywania danych, które można przeszukiwać, a które nie są przechowywane w czymś takim jak pole TEXTlub, NTEXTto VARCHARzapewnia miejsce o wartości 8k, podczas gdy NVARCHARzapewnia tylko 4k (podwójna liczba bajtów, podwójna przestrzeń).

Podsumowując, użycie jednego z nich zależy od:

  • Projekt lub kontekst
  • Infrastruktura
  • System bazy danych
Paweł
źródło
6

Śledź różnicę między typem VARCHAR serwera Sql a typem danych NVARCHAR . Tutaj możesz zobaczyć w bardzo opisowy sposób.

Ogólnie rzecz biorąc, nvarchar przechowuje dane jako Unicode, więc jeśli zamierzasz przechowywać dane wielojęzyczne (więcej niż jeden język) w kolumnie danych, potrzebujesz wariantu N.

Pradeep Kesharwani
źródło
To bardzo przydatny link, ale twoja odpowiedź nie jest niczym więcej: linkiem.
RubberDuck,
ckuhn203, nie powiem ci, żebyś to zobaczył
Pradeep Kesharwani,
6

Główną różnicą między Varchar(n)i nvarchar(n)jest: wprowadź opis zdjęcia tutaj

VarcharRozmiar (dane znakowe o zmiennej długości, inne niż Unicode) wynosi do 8000. 1. Jest to typ danych o zmiennej długości

  1. Służy do przechowywania znaków innych niż Unicode

  2. Zajmuje 1 bajt miejsca dla każdej postaci

wprowadź opis zdjęcia tutaj

Nvarchar: Dane znakowe Unicode o zmiennej długości.

1. Jest to typ danych o zmiennej długości

2. Używany do przechowywania znaków Unicode.

  1. Dane są przechowywane w kodowaniu Unicode. Obsługiwany jest każdy język. (na przykład języki arabski, niemiecki, hindi itp.)
Debendra Dash
źródło
6

Jeffrey L Whitledge z wynikiem ~ 47000 punktów reputacji zaleca użycie nvarchar

Solomon Rutzky z wynikiem ~ 33200 reputacji zaleca: NIE zawsze używaj NVARCHAR. Jest to bardzo niebezpieczne i często kosztowne podejście / podejście.

Jakie są główne różnice w wydajności między typami danych varchar i nvarchar SQL Server?

https://www.sqlservercentral.com/articles/disk-is-cheap-orly-4

Obie osoby o tak wysokiej reputacji, co wybiera deweloper uczącej się bazy danych serwerów SQL?

Istnieje wiele ostrzeżeń w odpowiedziach i komentarzach dotyczących problemów z wydajnością, jeśli nie jesteś konsekwentny w wyborze.

Istnieją komentarze pro / con nvarchar dotyczące wydajności.

Istnieją komentarze pro / con varchar dotyczące wydajności.

Mam szczególne wymagania dotyczące tabeli z wieloma setkami kolumn, co samo w sobie jest prawdopodobnie niezwykłe?

Wybieram varchar, aby uniknąć zbliżenia się do limitu rozmiaru rekordu tabeli rekordów 8060 bajtów serwera SQL * server 2012.

Użycie nvarchar przekracza dla mnie ten limit 8060 bajtów.

Myślę również, że powinienem dopasować typy danych powiązanych tabel kodów do typów danych podstawowej centralnej tabeli.

Widziałem użycie kolumny varchar w tym miejscu pracy, rząd Australii Południowej, przez poprzednich doświadczonych programistów baz danych, gdzie liczba wierszy tabeli będzie wynosić kilka milionów lub więcej (i bardzo niewiele kolumn nvarchar, jeśli w ogóle, w tych bardzo dużych tabele), więc być może oczekiwane objętości wierszy danych stają się częścią tej decyzji.

Allan F.
źródło
1

nvarcharjest bezpieczny w użyciu w porównaniu do tego varchar, aby nasz kod był wolny od błędów (niedopasowanie typu), ponieważ nvarcharpozwala również na znaki Unicode. Gdy użyjemy wherewarunku w zapytaniu SQL Server i jeśli użyjemy =operatora, to czasami wyrzuca błąd. Prawdopodobnym powodem jest to, że nasza kolumna mapowania będzie inna varchar. Gdybyśmy zdefiniowali to w nvarchartym problemie, to by się nie stało. Nadal trzymamy się varchartego problemu i unikamy go, lepiej LIKEraczej używać słowa kluczowego niż =.

Rinoy Ashokan
źródło