Należy również pamiętać, że podczas porównywania indeksów często występuje bardzo duża różnica między CHAR a VARCHAR
Czy dotyczy to / nadal dotyczy Postgres?
Znalazłem strony w Oracle, które twierdzą, że CHARjest to mniej więcej alias, VARCHARwięc wydajność indeksu jest taka sama, ale nie znalazłem nic ostatecznego w Postgres.
CHARi VARCHARsą implementowane dokładnie tak samo w Postgres (i Oracle). Podczas korzystania z tych typów danych nie ma różnicy prędkości.
Jest jednak jedna różnica, która może mieć wpływ na wydajność: charkolumna jest zawsze dopełniana do zdefiniowanej długości. Jeśli więc zdefiniujesz kolumnę jako char(100)i jeden jako, varchar(100)ale przechowujesz tylko 10 znaków w każdej z nich, char(100)kolumna używa 100 znaków dla każdej wartości (10 przechowywanych znaków plus 90 spacji), podczas gdy varcharkolumna przechowuje tylko 10 znaków.
Porównywanie 100 znaków ze 100 znakami będzie wolniejsze niż porównywanie 10 znaków z 10 znakami - chociaż wątpię, czy rzeczywiście można zmierzyć tę różnicę w zapytaniu SQL.
Jeśli zadeklarujesz zarówno długość 10 znaków, jak i zawsze przechowujesz w nich dokładnie 10 znaków, nie ma absolutnie żadnej różnicy (dotyczy to Oracle i Postgres)
Tak więc jedyną różnicą jest wypełnienie dla chartypu danych.
Należy również pamiętać, że podczas porównywania indeksów często występuje bardzo duża różnica między CHAR a VARCHAR
Powyższy cytat jest prawdziwy tylko wtedy, gdy (i tylko wtedy) charkolumna jest zdefiniowana zbyt szeroko (tzn. Marnujesz miejsce z powodu wypełnienia). Jeśli długość charkolumny jest zawsze używana w całości (więc nie występuje wypełnianie), to powyższy cytat jest błędny (przynajmniej dla Postgres i Oracle)
Z mojego punktu widzenia chartyp danych tak naprawdę nie ma zastosowania w prawdziwym słowie. Po prostu użyj varchar(lub textw Postgres) i zapomnij, że charistnieje.
Porównywanie 100 znaków ze 100 znakami będzie wolniejsze niż porównywanie 10 znaków z 10 znakami - chociaż wątpię, czy rzeczywiście można zmierzyć tę różnicę w zapytaniu SQL. - W zależności od tego, co robi zapytanie oprócz sortowania, różnica może być ogromna. Właśnie dlatego Postgres 9.5 ma nową funkcję „kluczy skróconych”: pgeoghegan.blogspot.de/2015/01/…
chirlu
6
Zgadzam się ze wszystkim , co powiedział a_horse_with_no_name, i ogólnie zgadzam się z poradą Erwina na komentarz:
Nie, char jest gorszy (i nieaktualny). tekst i varchar działają (prawie) tak samo.
Metadane
Z jednym drobnym wyjątkiem używam tylko wtedy, char()gdy chcę, aby metadane mówiły, że MUSI mieć znaki x. Chociaż wiem, że char()narzeka tylko wtedy, gdy wkład przekroczy limit, często zabezpieczam się przed niedopełnieniem w CHECKograniczeniu. Na przykład,
CREATETABLE foo (
x char(10)CHECK( length(x)=10));INSERTINTO foo VALUES(repeat('x',9));
Robię to z kilku powodów,
char(x)jest czasami wywnioskowany z ładujących schematy jako kolumna o stałej szerokości. Może to mieć znaczenie w języku zoptymalizowanym dla ciągów o stałej szerokości.
Ustanawia konwencję, która ma sens i jest łatwa do egzekwowania. Potrafię napisać moduł ładujący schematy w języku, aby wygenerować kod z tej konwencji.
Potrzebujesz przykładu, gdzie mogę to zrobić,
Dwuliterowe skróty stanu, chociaż ponieważ tę listę można wyliczyć, zwykle zrobię to za pomocą ENUM.
Zauważ, że niektórzy ludzie mogą czuć się niekomfortowo z niezgodnością komunikatów o błędach po obu stronach limitu, ale nie przeszkadza mi to
test=#INSERTINTO foo VALUES(repeat('x',9));
ERROR: new rowfor relation "foo" violates checkconstraint"foo_x_check"
DETAIL: Failing rowcontains(xxxxxxxxx ).
test=#INSERTINTO foo VALUES(repeat('x',11));
ERROR: value too long for type character(10)
Kontrastować z varchar
Co więcej, myślę, że powyższa sugestia bardzo dobrze pasuje do konwencji prawie zawsze używanejtext . Ty też pytasz varchar(n). Nigdy tego nie używam . Przynajmniej nie pamiętam, kiedy ostatni raz użyłem varchar(n).
Jeśli specyfikacja ma zaufane pole o statycznej szerokości, używam char(n),
W przeciwnym razie używam, textco jest efektywne varchar(bez limitu)
Gdybym znalazł specyfikację z kluczami tekstowymi o zmiennej długości, które były znaczące i że ufałem, że będę mieć stałą maksymalną długość, też bym użył varchar(n). Nie mogę jednak wymyślić niczego, co spełniałoby te kryteria.
sales_reporting_db=#createtable x (y char(2));CREATETABLE
sales_reporting_db=#insertinto x values('Y');INSERT01
sales_reporting_db=#select'*'|| y ||'*'from x;?column?----------*Y*
Wyrocznia
SQL>createtable x ( y char(2));Table created.
SQL>insertinto x values('Y');1row created.
SQL>select'*'|| y ||'*'from x;'*'|----*Y *
Zgadzam się ze wszystkim , co powiedział a_horse_with_no_name, i ogólnie zgadzam się z poradą Erwina na komentarz:
Metadane
Z jednym drobnym wyjątkiem używam tylko wtedy,
char()
gdy chcę, aby metadane mówiły, że MUSI mieć znaki x. Chociaż wiem, żechar()
narzeka tylko wtedy, gdy wkład przekroczy limit, często zabezpieczam się przed niedopełnieniem wCHECK
ograniczeniu. Na przykład,Robię to z kilku powodów,
char(x)
jest czasami wywnioskowany z ładujących schematy jako kolumna o stałej szerokości. Może to mieć znaczenie w języku zoptymalizowanym dla ciągów o stałej szerokości.Potrzebujesz przykładu, gdzie mogę to zrobić,
ENUM
.O błędach
Zauważ, że niektórzy ludzie mogą czuć się niekomfortowo z niezgodnością komunikatów o błędach po obu stronach limitu, ale nie przeszkadza mi to
Kontrastować z
varchar
Co więcej, myślę, że powyższa sugestia bardzo dobrze pasuje do konwencji prawie zawsze używanej
text
. Ty też pytaszvarchar(n)
. Nigdy tego nie używam . Przynajmniej nie pamiętam, kiedy ostatni raz użyłemvarchar(n)
.char(n)
,text
co jest efektywnevarchar
(bez limitu)Gdybym znalazł specyfikację z kluczami tekstowymi o zmiennej długości, które były znaczące i że ufałem, że będę mieć stałą maksymalną długość, też bym użył
varchar(n)
. Nie mogę jednak wymyślić niczego, co spełniałoby te kryteria.Dodatkowe uwagi
char
tutaj nie należy mylić z"char"
tym, że jest to typ jednobajtowy i ma solidną wydajność i oszczędność miejsca.Powiązane pytania i odpowiedzi:
źródło
Postgresql
Wyrocznia
Postgresql nie padał spacjami.
źródło
SELECT pg_column_size(y) FROM x;
Znalazłem to najbardziej przydatne i szybkie 3-liniowe objaśnienie:
źródło