Pracuję nad bazą danych dla małej aplikacji internetowej w mojej szkole SQL Server 2005
.
Widzę kilka szkół myślenia na temat varchar
vs nvarchar
:
- Używaj,
varchar
chyba że masz do czynienia z wieloma danymi międzynarodowymi, a następnie używajnvarchar
. - Po prostu użyj
nvarchar
do wszystkiego.
Zaczynam dostrzegać zalety widzenia 2. Wiem, że nvarchar zajmuje dwa razy więcej miejsca, ale to niekoniecznie wielka sprawa, ponieważ będzie to przechowywać dane tylko dla kilkuset studentów. Wydaje mi się, że najłatwiej byłoby nie przejmować się tym i po prostu pozwolić wszystkim korzystać z nvarchar. A może brakuje mi czegoś?
sql-server
sql-server-2005
storage
varchar
nvarchar
Jason Baker
źródło
źródło
NVARCHAR
” jest niepotrzebne i nieekonomiczne , i może mieć bardzo negatywny wpływ na wydajność i koszty / budżety sprzętu. Kilka rzędów, nawet kilka tysięcy, nie będzie miało znaczenia. Ale systemy rosną szybciej, niż ludzie się spodziewają, więc obecna akceptowana odpowiedź jest niekorzystna dla społeczności. Dziękuję Ci.Odpowiedzi:
Zawsze używaj nvarchar.
W większości aplikacji nigdy nie będziesz potrzebować znaków dwubajtowych. Jeśli jednak potrzebujesz obsługi języków dwubajtowych i masz obsługę tylko jednego bajtu w schemacie bazy danych, powrót i modyfikacja w całej aplikacji jest naprawdę kosztowna.
Koszt migracji jednej aplikacji z varchar do nvarchar będzie znacznie większy niż odrobina dodatkowego miejsca na dysku, którego będziesz używać w większości aplikacji.
źródło
Miejsce na dysku nie jest problemem ... ale pamięć i wydajność będą. Podwójna liczba odczytów strony, podwójny rozmiar indeksu, dziwne LIKE i = stałe zachowanie itp
Czy potrzebujesz przechowywać skrypt chiński itp.? Tak lub nie...
I od MS BOL „ Efekty przechowywania i wydajności Unicode ”
Edytuj :
Ostatnie pytanie SO podkreślające, jak niska wydajność nvarchar może być ...
SQL Server używa wysokiego procesora podczas wyszukiwania wewnątrz ciągów nvarchar
źródło
Bądź konsekwentny! DOŁĄCZENIE VARCHAR do NVARCHAR ma duży hit wydajności.
źródło
nvarchar
sięvarchar
a konwersjąnvarchar
dovarchar
i dołączaniem dovarchar
. Chyba że oczywiście chciałeś zachować spójność w typach kolumn, a nie dołączać.VARCHAR
iNVARCHAR
powinno to wynikać z indeksowaniaVARCHAR
kolumny wraz z rodzajem sortowania zastosowanym dla tej kolumny (i stąd indeksu). Szczegółowo omawiam ten temat w następującym poście na blogu: Wpływ na indeksy podczas mieszania typów VARCHAR i NVARCHAR .nvarchar będzie miał znaczne obciążenie pamięci, pamięci, zestawu roboczego i indeksowania, więc jeśli specyfikacje wskazują, że tak naprawdę nigdy nie będzie to konieczne, nie przejmuj się.
Nie miałbym twardej i szybkiej reguły „zawsze nvarchar”, ponieważ może to być kompletne marnotrawstwo w wielu sytuacjach - szczególnie ETL z ASCII / EBCDIC lub identyfikatorów i kolumn kodu, które często są kluczami i kluczami obcymi.
Z drugiej strony istnieje wiele przypadków kolumn, w których z pewnością zada mi się to pytanie wcześniej, a jeśli nie otrzymam szybkiej i szybkiej odpowiedzi od razu, utworzę kolumnę nvarchar.
źródło
Waham się, aby dodać tutaj kolejną odpowiedź, ponieważ jest już ich sporo, ale należy podać kilka kwestii, które albo nie zostały przedstawione, albo nie zostały jasno określone.
Po pierwsze: Czy nie zawsze używać
NVARCHAR
. Jest to bardzo niebezpieczne i często kosztowne podejście / podejście. I nie jest lepiej powiedzieć „ Nigdy nie używaj kursorów”, ponieważ czasami są one najskuteczniejszym sposobem rozwiązania określonego problemu, a wspólne obejście wykonywaniaWHILE
pętli prawie zawsze będzie wolniejsze niż poprawnie wykonany Kursor.Termin „zawsze” powinien być używany tylko wtedy, gdy zaleca się „zawsze robić to, co jest najlepsze w danej sytuacji”. To prawda, że często jest to trudne do ustalenia, szczególnie gdy próbuje się zrównoważyć krótkoterminowe zyski z czasu programowania (kierownik: „potrzebujemy tej funkcji - o której jeszcze nie wiedzieliście - tydzień temu!”) Z długim -terminowe koszty utrzymania (kierownik, który początkowo naciskał na zespół, aby ukończył 3-miesięczny projekt w 3-tygodniowym sprincie: „dlaczego mamy te problemy z wydajnością? Jak moglibyśmy zrobić X, który nie ma elastyczności? Nie możemy sobie pozwolić sprint lub dwa, aby to naprawić. Co możemy zrobić w ciągu tygodnia, abyśmy mogli wrócić do naszych priorytetowych przedmiotów? I zdecydowanie musimy spędzić więcej czasu na projektowaniu, aby tak się nie stało! ”).
Po drugie: odpowiedź @ gbn dotyczy kilku bardzo ważnych punktów, które należy wziąć pod uwagę przy podejmowaniu pewnych decyzji dotyczących modelowania danych, gdy ścieżka nie jest w 100% jasna. Ale jest jeszcze więcej do rozważenia:
Marnowanie przestrzeni ma ogromny efekt kaskadowy na cały system. Napisałem artykuł szczegółowo opisujący ten temat: Dysk jest tani! ORLY? (wymagana darmowa rejestracja; przepraszam, nie kontroluję tych zasad).
Po trzecie: chociaż niektóre odpowiedzi nieprawidłowo koncentrują się na aspekcie „jest to mała aplikacja”, a niektóre prawidłowo sugerują „wykorzystanie tego, co jest właściwe”, żadna z odpowiedzi nie przedstawiła rzeczywistych wskazówek dla PO Ważny szczegół wymieniony w pytaniu jest to, że jest to strona internetowa ich szkoły. Wspaniały! Możemy więc zasugerować, że:
NVARCHAR
ponieważ z czasem coraz bardziej prawdopodobne staje się pojawienie się nazwisk z innych kultur w tych miejscach.VARCHAR
odpowiedniej strony kodowej (która jest określany na podstawie sortowania pola).INT
/TINYINT
ponieważ kody ISO mają ustaloną długość, są czytelne dla człowieka i no cóż, standardowe :) użyjCHAR(2)
do kodów dwuliterowych iCHAR(3)
jeśli używasz kodów 3-literowych. I rozważ użycie binarnego sortowania, takiego jakLatin1_General_100_BIN2
.VARCHAR
ponieważ jest to międzynarodowy standard, aby nigdy nie używać żadnej litery poza AZ. I tak, nadal używaj,VARCHAR
nawet jeśli przechowujesz tylko amerykańskie kody pocztowe, a nie INT, ponieważ kody pocztowe nie są liczbami, są łańcuchami, a niektóre z nich mają wiodące „0”. I rozważ użycie binarnego sortowania, takiego jakLatin1_General_100_BIN2
.NVARCHAR
ponieważ oba mogą teraz zawierać znaki Unicode.Po czwarte: teraz, gdy
NVARCHAR
dane zajmują dwa razy więcej miejsca niż potrzeba dla danych, które ładnie się pasująVARCHAR
(„ładnie pasuje” = nie zamienia się w „?”) I jakoś, jakby magicznie, aplikacja się rozrosła a teraz są miliony rekordów w co najmniej jednym z tych pól, w których większość wierszy jest standardowym kodem ASCII, ale niektóre zawierają znaki Unicode, więc musisz je zachowaćNVARCHAR
, rozważ następujące kwestie:Jeśli używasz programu SQL Server 2008 - 2016 RTM i korzystasz z wersji Enterprise Edition, LUB jeśli korzystasz z programu SQL Server 2016 z dodatkiem SP1 (który udostępnił kompresję danych we wszystkich edycjach) lub nowszym, możesz włączyć kompresję danych . Kompresja danych może (ale nie zawsze) kompresuje dane
NCHAR
iNVARCHAR
pola Unicode . Czynnikami determinującymi są:NCHAR(1 - 4000)
iNVARCHAR(1 - 4000)
użyj standardowego schematu kompresji dla Unicode , ale tylko w SQL Server 2008 R2, ORAZ tylko dla danych IN ROW, a nie PRZEKROCZENIA! To wydaje się być lepsze niż zwykły algorytm kompresji ROW / PAGE.NVARCHAR(MAX)
iXML
(i chyba równieżVARBINARY(MAX)
,TEXT
iNTEXT
) dane, które są w rzędzie (nie od wiersza LOB lub przelewowe strony) mogą być co najmniej PAGE sprężonego ale nie Rów ściśnięta. Oczywiście kompresja PAGE zależy od wielkości wartości w wierszu: przetestowałem za pomocą VARCHAR (MAX) i zobaczyłem, że wiersze 6000 znaków / bajtów nie ulegają kompresji, ale wiersze 4000 znaków / bajtów tak.Jeśli używasz programu SQL Server 2005 lub 2008-2016 RTM, a nie wersji Enterprise Edition, możesz mieć dwa pola: jedno
VARCHAR
i jednoNVARCHAR
. Załóżmy na przykład, że przechowujesz adresy URL, które w większości są podstawowymi znakami ASCII (wartości 0–127), a zatem pasują doVARCHAR
, ale czasami mają znaki Unicode. Twój schemat może zawierać następujące 3 pola:W tym modelu WYBIERASZ tylko z
[URL]
kolumny obliczeniowej. Do wstawiania i aktualizowania decydujesz, którego pola użyć, sprawdzając, czy konwersja zmienia wartość wejściową, która musi byćNVARCHAR
typu:Możesz GZIP przychodzące wartości do,
VARBINARY(MAX)
a następnie rozpakuj po wyjściu:COMPRESS
iDECOMPRESS
funkcji, które są także GZip.Jeśli korzystasz z programu SQL Server 2017 lub nowszego, możesz sprawdzić, czy tabela stanie się Clustered Columnstore Index.
Chociaż nie jest to jeszcze opłacalna opcja, SQL Server 2019 wprowadza natywną obsługę UTF-8 w
VARCHAR
/CHAR
typy danych. Obecnie jest z nim zbyt wiele błędów, aby można go było użyć, ale jeśli zostaną naprawione, jest to opcja w niektórych scenariuszach. Zapoznaj się z moim postem „ Natywna obsługa UTF-8 w programie SQL Server 2019: Zbawiciel czy fałszywy prorok? ”, Aby uzyskać szczegółową analizę tej nowej funkcji.źródło
W przypadku Twojej aplikacji nvarchar jest w porządku, ponieważ rozmiar bazy danych jest mały. Powiedzenie „zawsze używaj nvarchar” jest ogromnym uproszczeniem. Jeśli nie musisz przechowywać takich rzeczy jak Kanji lub inne zwariowane postacie, użyj VARCHAR, zajmie to o wiele mniej miejsca. Mój poprzednik w mojej obecnej pracy zaprojektował coś przy użyciu NVARCHAR, gdy nie było to potrzebne. Niedawno zmieniliśmy go na VARCHAR i zaoszczędziliśmy 15 GB na tym samym stole (do czego był bardzo napisany). Ponadto, jeśli masz indeks w tej tabeli i chcesz dołączyć tę kolumnę lub utworzyć indeks złożony, właśnie zwiększyłeś rozmiar pliku indeksu.
Po prostu rozważ swoją decyzję; w rozwoju SQL i definicjach danych rzadko wydaje się, że istnieje „domyślna odpowiedź” (oczywiście poza unikaniem kursorów za wszelką cenę).
źródło
Ponieważ Twoja aplikacja jest niewielka, korzystanie z nvarchar w porównaniu z varchar zasadniczo nie powoduje znacznego wzrostu kosztów, a jeśli chcesz przechowywać dane w trybie Unicode, oszczędzasz sobie potencjalnych problemów.
źródło
Ogólnie rzecz biorąc; Zacznij od najdroższego typu danych, który ma najmniejsze ograniczenia. Umieść go w produkcji . Jeśli wydajność zaczyna być problemem, dowiedz się, co faktycznie jest przechowywane w tych
nvarchar
kolumnach. Czy są tam jakieś postacie, które nie pasowałybyvarchar
? Jeśli nie, zmień na varchar. Nie próbuj wstępnie optymalizować, zanim będziesz wiedział, gdzie jest ból. Domyślam się, że wybór pomiędzy nvarchar / varchar nie jest tym, co spowolni twoją aplikację w dającej się przewidzieć przyszłości. Będą też inne części aplikacji, w których dostrajanie wydajności zapewni znacznie więcej pieniędzy .źródło
Przez ostatnie kilka lat wszystkie nasze projekty wykorzystywały NVARCHAR do wszystkiego, ponieważ wszystkie te projekty są wielojęzyczne. Zaimportowane dane ze źródeł zewnętrznych (np. Plik ASCII itp.) Są konwertowane do formatu Unicode przed włożeniem do bazy danych.
Nie spotkałem się jeszcze z żadnymi problemami związanymi z wydajnością z większych indeksów itp. Indeksy zużywają więcej pamięci, ale pamięć jest tania.
Niezależnie od tego, czy korzystasz z procedur przechowywanych, czy konstruujesz SQL w locie, upewnij się, że wszystkie stałe ciągów są poprzedzone N (np. SET @foo = N'Hello world. ';), Aby stała była również Unicode. Pozwala to uniknąć konwersji typu łańcucha w czasie wykonywania.
YMMV.
źródło
Mogę o tym mówić z doświadczenia, strzeżcie się
nvarchar
. O ile nie jest to absolutnie wymagane, ten typ pola danych niszczy wydajność w większej bazie danych. Odziedziczyłem bazę danych, która szkodziła pod względem wydajności i przestrzeni. Udało nam się zmniejszyć rozmiar bazy danych 30 GB o 70%! Wprowadzono kilka innych modyfikacji, aby poprawić wydajność, ale jestem pewien, żevarchar
znacznie pomogły również w tym. Jeśli Twoja baza danych ma potencjał do powiększenia tabel do ponad miliona rekordów, trzymaj się z dala odnvarchar
wszelkich kosztów.źródło
Często zadaję sobie to pytanie w pracy:
Kanały FTP z zapasami i cenami - opisy produktów i inne teksty znajdowały się w nvarchar, gdy varchar działał poprawnie. Przekształcenie ich w varchar zmniejszyło rozmiar pliku prawie o połowę i naprawdę pomogło w przesyłaniu.
Powyższy scenariusz działał dobrze, dopóki ktoś nie umieścił znaku specjalnego w opisie przedmiotu (być może znak towarowy, nie pamiętam)
Nadal nie używam nvarchar za każdym razem nad varchar. Jeśli są jakieś wątpliwości lub potencjał dla znaków specjalnych, używam nvarchar. Uważam, że używam varchar głównie wtedy, gdy mam 100% kontrolę nad tym, co wypełnia pole.
źródło
Dlaczego w całej tej dyskusji nie wspomniano o UTF-8? Możliwość przechowywania pełnego zakresu znaków Unicode nie oznacza, że należy zawsze przydzielić dwa bajty na znak (lub „punkt kodowy”, aby użyć terminu UNICODE). Wszystkie ASCII to UTF-8. Czy SQL Server sprawdza dla pól VARCHAR (), że tekst jest ścisły ASCII (tj. Bit najwyższego bajtu zero)? Miałbym nadzieję, że nie.
Jeśli następnie chcesz zapisać Unicode i chcesz kompatybilność ze starszymi aplikacjami tylko ASCII, pomyślałbym, że użycie VARCHAR () i UTF-8 byłoby magiczną kulą: Zużywa więcej miejsca, gdy jest to konieczne.
Dla tych z was, którzy nie znają UTF-8, polecam podkład .
źródło
N
typy z prefiksem). Nie masz wyboru korzystania z UTF-8. Ponadto kodowania Unicode (UTF-8, UCS-2 / UTF-16 i UTF-32) nie można zastosować do pól VARCHAR.Będą wyjątkowe sytuacje, gdy będziesz chciał celowo ograniczyć typ danych, aby upewnić się, że nie zawiera on znaków z określonego zestawu. Na przykład miałem scenariusz, w którym musiałem przechowywać nazwę domeny w bazie danych. Internacjonalizacja nazw domen nie była wówczas niezawodna, dlatego lepiej ograniczyć wprowadzanie danych na poziomie podstawowym i pomóc uniknąć potencjalnych problemów.
źródło
Jeśli używasz
NVARCHAR
tylko dlatego, że systemowa procedura przechowywana tego wymaga, najczęstsze wystąpienie jest niewytłumaczalnesp_executesql
, a Twój dynamiczny SQL jest bardzo długi, lepiej byłoby z perspektywy wydajności wykonywać wszystkie operacje na łańcuchach (konkatenacja, zamiana itp.) WVARCHAR
konwersji wynik końcowyNVARCHAR
i wprowadzenie go do parametru proc. Więc nie, nie zawsze używajNVARCHAR
!źródło