Zdaję sobie sprawę, że CHAR jest zalecane, jeśli wszystkie moje wartości mają stałą szerokość. No i co z tego? Dlaczego po prostu wybrać VARCHAR dla wszystkich pól tekstowych, aby być bezpiecznym.
Zdaję sobie sprawę, że CHAR jest zalecane, jeśli wszystkie moje wartości mają stałą szerokość. No i co z tego? Dlaczego po prostu wybrać VARCHAR dla wszystkich pól tekstowych, aby być bezpiecznym.
Odpowiedzi:
Zasadniczo wybierz CHAR, jeśli wszystkie rzędy będą miały zbliżoną długość . Wybierz VARCHAR, gdy długość różni się znacznie. CHAR może być również nieco szybszy, ponieważ wszystkie rzędy mają tę samą długość.
Różni się w zależności od implementacji DB, ale ogólnie VARCHAR wykorzystuje jeden lub dwa dodatkowe bajty pamięci (dla długości lub zakończenia) oprócz rzeczywistych danych. Więc (zakładając, że używasz jednobajtowego zestawu znaków) przechowującego słowo „FooBar”
Najważniejsze jest to, że CHAR może być szybszy i zajmować więcej miejsca dla danych o stosunkowo tej samej długości (w obrębie różnicy długości dwóch znaków).
Uwaga : Microsoft SQL ma 2 bajty narzutu dla VARCHAR. Może się to różnić od DB do DB, ale generalnie potrzebny jest co najmniej 1 bajt narzutu potrzebny do wskazania długości lub EOL na VARCHAR.
Jak zauważył Gaven w komentarzach, jeśli używasz wielobajtowego zestawu znaków o zmiennej długości, takiego jak UTF8, to CHAR przechowuje maksymalną liczbę bajtów niezbędną do przechowywania liczby znaków. Więc jeśli UTF8 potrzebuje maksymalnie 3 bajty do przechowywania znaku, to CHAR (6) zostanie ustalony na 18 bajtów, nawet jeśli przechowuje tylko znaki Latin1. W takim przypadku VARCHAR staje się znacznie lepszym wyborem.
Jeśli pracujesz ze mną i pracujesz z Oracle, prawdopodobnie użyłbym cię varchar
w prawie każdych okolicznościach. Założenie, że char
zużywa mniej mocy obliczeniowej, niż varchar
może być prawdą ... na razie ... ale silniki baz danych z czasem stają się lepsze, a tego rodzaju ogólna reguła tworzy przyszły „mit”.
Kolejna rzecz: nigdy nie widziałem problemu z wydajnością, ponieważ ktoś zdecydował się pójść varchar
. Znacznie lepiej wykorzystasz swój czas, pisząc dobry kod (mniej wywołań bazy danych) i wydajny SQL (jak działają indeksy, jak optymalizator podejmuje decyzje, dlaczego jest exists
szybszy niż in
zwykle ...).
Ostatnia myśl: widziałem różnego rodzaju problemy z używaniem CHAR
, ludzi szukających „”, gdy powinni szukać ”, lub osób szukających„ FOO ”, gdy powinni szukać„ FOO ”(tutaj jest kilka miejsc) lub ludzie, którzy nie przycinają końcowych spacji, lub błędy z Powerbuilderem dodającym do 2000 spacji do wartości zwracanej przez procedurę Oracle.
Oprócz korzyści związanych z wydajnością CHAR
można zastosować, aby wskazać, że wszystkie wartości powinny być tej samej długości, np. Kolumna dla skrótów stanów USA.
CHAR
, musisz upewnić się, że twoje ograniczenia rabują wypełnienie.
Char jest trochę szybszy, więc jeśli masz kolumnę, której WIEDZIE będzie pewnej długości, użyj char. Na przykład przechowywanie (M) ale / (F) emale / (U) nieznany dla płci lub 2 znaki dla stanu USA.
Czy NChar lub Char działają lepiej niż ich alternatywne warianty?
Świetne pytanie. Prosta odpowiedź brzmi „tak” w niektórych sytuacjach. Zobaczmy, czy można to wyjaśnić.
Oczywiście wszyscy wiemy, że jeśli utworzę tabelę z kolumną varchar (255) (nazwijmy tę kolumnę myColumn) i wstawię milion wierszy, ale wstawię tylko kilka znaków do myColumn dla każdego wiersza, tabela będzie znacznie mniejsza (ogólnie liczba stron danych potrzebnych silnikowi pamięci) niż gdybym utworzył moją kolumnę jako char (255). Za każdym razem, gdy wykonuję operację (DML) na tej tabeli i żądam wielu wierszy, będzie szybciej, gdy moja kolumna jest varchar, ponieważ nie muszę się ruszać po tych wszystkich „dodatkowych” miejscach na końcu. Przenieś, jak w przypadku, gdy SQL Server wykonuje wewnętrzne sortowania, takie jak podczas operacji oddzielania lub łączenia, lub jeśli wybiera scalanie podczas swojego planu zapytań itp.
Ale korzystanie z varchar wiąże się z pewnym nakładem. SQL Server musi używać dwubajtowego wskaźnika (narzutu), aby w każdym wierszu wiedzieć, ile bajtów ma w nim kolumna myColumn danego wiersza. Problemem nie są dodatkowe 2 bajty, to konieczność „dekodowania” długości danych w mojej kolumnie w każdym wierszu.
Z moich doświadczeń wynika, że najbardziej sensowne jest używanie char zamiast varchar w kolumnach, do których będą dołączane zapytania. Na przykład klucz podstawowy tabeli lub inna kolumna, która będzie indeksowana. CustomerNumber w tabeli demograficznej lub CodeID w tabeli dekodowania, a może OrderNumber w tabeli zamówień. Używając char, silnik zapytań może szybciej wykonać łączenie, ponieważ może wykonywać arytmetykę prostych wskaźników (deterministycznie) zamiast przesuwać swoje wskaźniki o zmienną liczbę bajtów podczas odczytywania stron. Wiem, że mogłem cię zgubić w ostatnim zdaniu. Połączenia w SQL Server są oparte na idei „predykatów”. Predykat jest warunkiem. Na przykład myColumn = 1 lub OrderNumber <500.
Jeśli więc SQL Server wykonuje instrukcję DML, a predykaty lub łączone „klucze” mają stałą długość (char), silnik zapytań nie musi wykonywać tyle pracy, aby dopasować wiersze z jednej tabeli do wierszy od inny stół. Nie będzie musiał dowiedzieć się, jak długo dane znajdują się w wierszu, a następnie przejdź wzdłuż ciągu znaków, aby znaleźć koniec. Wszystko to wymaga czasu.
Teraz pamiętaj, że można to łatwo źle wdrożyć. Widziałem char używane do pól klucza podstawowego w systemach online. Szerokość musi być mała, tzn. Char (15) lub coś rozsądnego. I działa najlepiej w systemach online, ponieważ zwykle pobierasz lub wstawiasz tylko niewielką liczbę wierszy, więc konieczność „przycięcia” tych końcowych spacji, które otrzymasz w zestawie wyników, jest trywialnym zadaniem, a nie dołączaniem do milionów wiersze z jednej tabeli do milionów wierszy w innej tabeli.
Innym powodem, dla którego CHAR ma sens w porównaniu z varchar w systemach online, jest to, że zmniejsza podział stron. Używając char, zasadniczo „rezerwujesz” (i marnujesz) to miejsce, więc jeśli użytkownik przyjdzie później i umieści więcej danych w tej kolumnie, SQL już przydzielił dla niego miejsce i idzie.
Kolejny powód do użycia CHAR jest podobny do drugiego. Jeśli programista lub użytkownik wykona aktualizację „wsadową” do milionów wierszy, dodając na przykład jakieś zdanie do pola notatki, nie dostaniesz połączenia z DBA w środku nocy, zastanawiając się, dlaczego ich dyski są pełne. Innymi słowy, prowadzi to do bardziej przewidywalnego wzrostu wielkości bazy danych.
Są to 3 sposoby, w jakie system online (OLTP) może korzystać z char w porównaniu z varchar. Prawie nigdy nie używam char w scenariuszu hurtowni / analizy / OLAP, ponieważ zwykle masz tak dużo danych, że wszystkie te kolumny char mogą zsumować wiele zmarnowanego miejsca.
Należy pamiętać, że char może znacznie zwiększyć bazę danych, ale większość narzędzi do tworzenia kopii zapasowych ma kompresję danych, więc kopie zapasowe mają zwykle taki sam rozmiar, jak gdybyś używał varchar. Na przykład LiteSpeed lub RedGate SQL Backup.
Innym zastosowaniem są widoki utworzone do eksportowania danych do pliku o stałej szerokości. Powiedzmy, że muszę wyeksportować niektóre dane do płaskiego pliku, aby mógł je odczytać komputer mainframe. Jest to stała szerokość (nie jest ograniczona). Lubię przechowywać dane w mojej tabeli „pomostowej” jako varchar (zużywając w ten sposób mniej miejsca w mojej bazie danych), a następnie używam widoku do CAST wszystkiego do wartości równoważnej char, o długości odpowiadającej szerokości stałej szerokości dla tej kolumny . Na przykład:
create table tblStagingTable (
pkID BIGINT (IDENTITY,1,1),
CustomerFirstName varchar(30),
CustomerLastName varchar(30),
CustomerCityStateZip varchar(100),
CustomerCurrentBalance money )
insert into tblStagingTable
(CustomerFirstName,CustomerLastName, CustomerCityStateZip) ('Joe','Blow','123 Main St Washington, MD 12345', 123.45)
create view vwStagingTable AS
SELECT CustomerFirstName = CAST(CustomerFirstName as CHAR(30)),
CustomerLastName = CAST(CustomerLastName as CHAR(30)),
CustomerCityStateZip = CAST(CustomerCityStateZip as CHAR(100)),
CustomerCurrentBalance = CAST(CAST(CustomerCurrentBalance as NUMERIC(9,2)) AS CHAR(10))
SELECT * from vwStagingTable
To jest fajne, ponieważ wewnętrznie moje dane zajmują mniej miejsca, ponieważ używają varchar. Ale kiedy używam DTS lub SSIS, a nawet po prostu wycinam i wklejam z SSMS do Notatnika, mogę korzystać z widoku i uzyskać odpowiednią liczbę końcowych spacji. W DTS mieliśmy funkcję o nazwie, cholera, zapomniałem, że myślę, że nazywała się „sugeruj kolumny” lub coś w tym rodzaju. W SSIS nie możesz już tego robić, musisz żmudnie zdefiniować menedżera połączeń plików płaskich. Ale ponieważ masz skonfigurowany widok, SSIS może znać szerokość każdej kolumny i może zaoszczędzić dużo czasu podczas budowania zadań przepływu danych.
Więc dolna linia ... użyj varchar. Istnieje bardzo mała liczba powodów, dla których warto użyć char i tylko z powodów wydajnościowych. Jeśli masz system z setkami milionów wierszy, zobaczysz zauważalną różnicę, jeśli predykaty są deterministyczne (char), ale dla większości systemów używających char po prostu marnuje miejsce.
Mam nadzieję, że to pomaga. Jeff
Są korzyści z wydajności, ale tutaj jest jedna, o której nie wspomniano: migracja wierszy. Dzięki char rezerwujesz z wyprzedzeniem całą przestrzeń, więc powiedzmy, że masz char (1000) i przechowujesz 10 znaków, zużyjesz wszystkie 1000 charaterów przestrzeni. W varchar2 (1000) użyjesz tylko 10 znaków. Problem pojawia się podczas modyfikowania danych. Załóżmy, że zaktualizowałeś kolumnę, aby teraz zawierała 900 znaków. Możliwe jest, że przestrzeń do rozwinięcia varchara nie będzie dostępna w bieżącym bloku. W takim przypadku silnik DB musi migrować wiersz do innego bloku i utworzyć wskaźnik w oryginalnym bloku do nowego wiersza w nowym bloku. Aby odczytać te dane, silnik DB będzie musiał teraz odczytać 2 bloki.
Nikt nie może jednoznacznie powiedzieć, że varchar lub char są lepsze. Jest miejsce na kompromis czasowy i rozważenie, czy dane zostaną zaktualizowane, zwłaszcza jeśli istnieje duża szansa, że wzrosną.
Istnieje różnica między wczesną optymalizacją wydajności a zastosowaniem reguły typu najlepszych praktyk. Jeśli tworzysz nowe tabele, w których zawsze będziesz mieć pole o stałej długości, warto użyć CHAR, w takim przypadku powinieneś go użyć. To nie jest wczesna optymalizacja, ale raczej wdrożenie praktycznej reguły (lub najlepszej praktyki).
tj. - Jeśli masz dwuliterowe pole stanu, użyj CHAR (2). Jeśli masz pole z rzeczywistymi nazwami stanów, użyj VARCHAR.
Wybrałbym varchar, chyba że kolumna przechowuje stałą wartość, taką jak kod stanu USA - który zawsze ma 2 znaki, a lista prawidłowych kodów stanów USA nie zmienia się często :).
W każdym innym przypadku, nawet jak przechowywanie zaszyfrowanego hasła (o stałej długości), wybrałbym varchar.
Dlaczego - kolumna typu char jest zawsze wypełniana spacjami, co powoduje, że kolumna my_column zdefiniowana jako char (5) z wartością „ABC” wewnątrz porównania:
my_column = 'ABC' -- my_column stores 'ABC ' value which is different then 'ABC'
fałszywe.
Ta funkcja może prowadzić do wielu irytujących błędów podczas programowania i utrudnia testowanie.
CHAR zajmuje mniej miejsca niż VARCHAR, jeśli wszystkie wartości danych w tym polu są tej samej długości. Być może teraz w 2009 r. Baza danych o pojemności 800 GB jest taka sama pod każdym względem, jak 810 GB, jeśli przekształciłeś VARCHAR na CHAR, ale w przypadku krótkich ciągów (1 lub 2 znaków), CHAR jest nadal „najlepszą praktyką” w branży.
Teraz, gdy spojrzysz na szeroką gamę typów danych, które większość baz danych zapewnia nawet dla liczb całkowitych (bit, malutki, int, bigint), istnieją powody, aby wybrać jeden z nich. Po prostu wybranie biginta za każdym razem jest właściwie trochę nieświadome celów i zastosowań tej dziedziny. Jeśli pole po prostu reprezentuje wiek osoby w latach, bigint jest przesadą. Teraz niekoniecznie jest to „złe”, ale nie jest wydajne.
Ale to ciekawy argument, a ponieważ bazy danych poprawiają się z czasem, można argumentować, że CHAR vs VARCHAR staje się mniej istotny.
Opieram się na komentarzu Jima McKeetha.
Ponadto indeksowanie i pełne skanowanie tabeli są szybsze, jeśli tabela ma tylko kolumny CHAR. Zasadniczo optymalizator będzie w stanie przewidzieć, jak duży jest każdy rekord, jeśli ma tylko kolumny CHAR, podczas gdy musi sprawdzić wartość wielkości każdej kolumny VARCHAR.
Poza tym, jeśli zaktualizujesz kolumnę VARCHAR do rozmiaru większego niż jej poprzednia zawartość, możesz zmusić bazę danych do odbudowania jej indeksów (ponieważ zmusiłeś bazę danych do fizycznego przeniesienia rekordu na dysk). Podczas gdy z kolumnami CHAR nigdy się to nie wydarzy.
Ale prawdopodobnie nie zależy ci na wydajności, chyba że Twój stół jest ogromny.
Pamiętajcie o mądrych słowach Djikstry. Wczesna optymalizacja wydajności jest źródłem wszelkiego zła.
CHAR
kolumny indeksy również muszą zostać zaktualizowane. Pod tym względem nie ma różnicy w aktualizacji kolumny VARCHAR lub CHAR. Pomyśl o aktualizacji FOO
do BAR
.
Wiele osób zauważyło, że jeśli znasz dokładną długość wartości, użycie CHAR ma pewne zalety. Ale mimo że przechowywanie stanów USA jako CHAR (2) jest dziś świetne, kiedy otrzymujesz wiadomość ze sprzedaży, że „Właśnie dokonaliśmy naszej pierwszej sprzedaży do Australii”, jesteś w świecie bólu. Zawsze przesyłam, aby przecenić, jak długo, jak sądzę, pola będą musiały być, zamiast „dokładnego” przypuszczenia, by pokryć przyszłe wydarzenia. VARCHAR zapewni mi większą elastyczność w tym obszarze.
Myślę, że w twoim przypadku prawdopodobnie nie ma powodu, aby nie wybierać Varchara. Daje to elastyczność i, jak już wspomniano wielu respondentów, wydajność jest teraz taka, że oprócz bardzo szczególnych okoliczności, my, śmiertelnicy (w przeciwieństwie do Google DBA) nie zauważymy różnicy.
Interesującą rzeczą wartą odnotowania, jeśli chodzi o typy DB, jest sqlite (popularna mini baza danych o dość imponującej wydajności) umieszczająca wszystko w bazie danych jako ciąg i typy w locie.
Zawsze używam VarChar i zwykle robię to znacznie większym, niż mógłbym potrzebować. Na przykład. 50 za imię, jak mówisz, dlaczego nie po prostu być bezpiecznym.
NIGDY nie używałbym znaków. Dyskutowałem z wieloma osobami i zawsze przywołują zmęczone stereotypy, że char jest szybszy. Cóż, mówię, o ile szybciej? O czym tu mówimy, milisekundach, sekundach, a jeśli tak, ile? Mówisz mi, bo ktoś twierdzi, że to kilka milisekund szybciej, czy powinniśmy wprowadzić mnóstwo trudnych do naprawienia błędów w systemie?
Oto kilka problemów, na które napotkasz:
Każde pole zostanie uzupełnione, więc na zawsze otrzymasz kod, który ma wszędzie RTRIMS. Jest to również ogromne marnotrawstwo miejsca na dysku dla dłuższych pól.
Powiedzmy, że masz kwintesencję przykładu pola znakowego złożonego tylko z jednej postaci, ale pole jest opcjonalne. Jeśli ktoś przekazuje pusty ciąg do tego pola, staje się on jedną spacją. Gdy więc inna aplikacja / proces zapyta go, otrzymają jedną spację, jeśli nie używają rtrim. Mamy dokumenty XML, pliki i inne programy, wyświetlamy tylko jedno miejsce, w opcjonalnych polach i psujemy rzeczy.
Więc teraz musisz upewnić się, że przekazujesz wartości null, a nie pusty ciąg znaków, do pola char. Ale to NIE jest prawidłowe użycie wartości null. Oto użycie wartości null. Powiedzmy, że otrzymujesz plik od dostawcy
Imię | Płeć | Miasto
Bob || Los Angeles
Jeśli płeć nie jest określona, wpisz Bob, pusty ciąg i Los Angeles do tabeli. Powiedzmy teraz, że otrzymujesz plik i jego zmiany formatu, a płeć nie jest już uwzględniona, ale była w przeszłości.
Nazwa | Miasto
Bob | Seattle
Teraz, ponieważ płeć nie jest uwzględniona, użyłbym null. Varchars obsługują to bez problemów.
Z drugiej strony Char jest inny. Zawsze musisz wysłać zero. Jeśli kiedykolwiek wyślesz pusty ciąg, skończysz z polem zawierającym spacje.
Mógłbym bez końca ze wszystkimi błędami, które musiałem naprawić z postaci i przez około 20 lat rozwoju.
Przy obliczaniu rzeczywistej potrzebnej wielkości wartości kolumny i przydzielaniu miejsca dla Varchara istnieje pewien niewielki narzut związany z przetwarzaniem, więc jeśli masz pewność, jak długo ta wartość będzie zawsze, lepiej użyć Char i uniknąć trafienia.
To klasyczna przestrzeń kontra wydajność.
W MS SQL 2005 Varchar (lub NVarchar dla sieci wymagających dwóch bajtów na znak, tj. Chiński) ma zmienną długość. Jeśli dodasz do wiersza po zapisaniu go na dysku twardym, zlokalizuje on dane w niezainteresowanym miejscu do oryginalnego wiersza i doprowadzi do fragmentacji plików danych. Wpłynie to na wydajność.
Tak więc, jeśli przestrzeń nie jest problemem, Char jest lepszy pod względem wydajności, ale jeśli chcesz zmniejszyć rozmiar bazy danych, lepiej są varchary.
Podział. Char rezerwuje miejsce, a VarChar nie. Podział strony może być wymagany w celu dostosowania aktualizacji do varchar.
CHAR
kolumny może dojść do podziału strony .
W niektórych bazach danych SQL VARCHAR zostanie uzupełniony do maksymalnego rozmiaru w celu zoptymalizowania przesunięć. Jest to przyspieszenie pełnego skanowania tabel i indeksów.
Z tego powodu nie masz żadnych oszczędności miejsca dzięki użyciu VARCHAR (200) w porównaniu do CHAR (200)
Korzystanie z CHAR (NCHAR) i VARCHAR (NVARCHAR) wprowadza różnice w sposobie przechowywania danych przez serwer bazy danych. Pierwszy wprowadza spacje końcowe; Wystąpił problem podczas używania go z operatorem LIKE w funkcjach SQL SERVER. Muszę więc zapewnić bezpieczeństwo, używając VARCHAR (NVARCHAR) przez cały czas.
Na przykład, jeśli mamy tabelę TEST (ID INT, Status CHAR (1)) , a ty piszesz funkcję, aby wyświetlić listę wszystkich rekordów o określonej wartości, takich jak:
CREATE FUNCTION List(@Status AS CHAR(1) = '')
RETURNS TABLE
AS
RETURN
SELECT * FROM TEST
WHERE Status LIKE '%' + @Status '%'
W tej funkcji oczekujemy, że po wstawieniu parametru domyślnego funkcja zwróci wszystkie wiersze, ale w rzeczywistości tak nie jest. Zmień typ danych @Status na VARCHAR naprawi problem.