Lembre-se também de que muitas vezes há uma grande diferença entre um CHAR e um VARCHAR ao fazer comparações de índice
Isso se aplica / ainda se aplica ao Postgres?
Encontrei páginas no Oracle afirmando que CHARé mais ou menos um alias para VARCHARe, portanto, o desempenho do índice é o mesmo, mas não encontrei nada definitivo no Postgres.
CHARe VARCHARsão implementados exatamente da mesma forma no Postgres (e Oracle). Não há diferença de velocidade ao usar esses tipos de dados.
No entanto, há uma diferença que pode fazer a diferença no desempenho: uma charcoluna é sempre preenchida no comprimento definido. Portanto, se você definir uma coluna como char(100)e uma como varchar(100)armazenar apenas 10 caracteres em cada uma, a char(100)coluna usará 100 caracteres para cada valor (os 10 caracteres armazenados, mais 90 espaços), enquanto a varcharcoluna armazena apenas 10 caracteres.
Comparar 100 caracteres com 100 caracteres será mais lento do que comparar 10 caracteres com 10 caracteres - embora eu duvide que você possa realmente medir essa diferença em uma consulta SQL.
Se você declarar ambos com o comprimento de 10 caracteres e sempre armazenar exatamente 10 caracteres, não haverá absolutamente nenhuma diferença (isso é verdade para Oracle e Postgres)
Portanto, a única diferença é o preenchimento feito para o chartipo de dados.
Lembre-se também de que muitas vezes há uma grande diferença entre um CHAR e um VARCHAR ao fazer comparações de índice
A citação acima só é verdadeira se (e somente se) a charcoluna estiver definida muito ampla (isto é, você está desperdiçando espaço devido ao preenchimento). Se o comprimento da charcoluna for sempre usado completamente (para que não ocorra preenchimento), a cotação acima estará errada (pelo menos para Postgres e Oracle)
Do meu ponto de vista, o chartipo de dados realmente não tem uso de palavras reais. Basta usar varchar(ou textno Postgres) e esquecer que charexiste.
Comparar 100 caracteres com 100 caracteres será mais lento do que comparar 10 caracteres com 10 caracteres - embora eu duvide que você possa realmente medir essa diferença em uma consulta SQL. - Dependendo do que a consulta faz, além da classificação, a diferença pode ser enorme. É por isso que o Postgres 9.5 possui um novo recurso de "chaves abreviadas": pgeoghegan.blogspot.de/2015/01/…
chirlu
6
Concordo com tudo o que foi dito por a_horse_with_no_name, e geralmente concordo com os conselhos de comentários de Erwin:
Não, char é inferior (e desatualizado). text e varchar executam (quase) o mesmo.
Metadados
Com uma pequena exceção, a única vez que uso char()é quando quero que os metadados digam que DEVE ter caracteres x. Embora eu saiba que char()apenas reclame se a entrada estiver acima do limite, frequentemente protegerei contra subidas devido a uma CHECKrestrição. Por exemplo,
CREATETABLE foo (
x char(10)CHECK( length(x)=10));INSERTINTO foo VALUES(repeat('x',9));
Eu faço isso por alguns motivos,
char(x)às vezes é inferido com carregadores de esquema como sendo uma coluna de largura fixa. Isso pode fazer a diferença em um idioma otimizado para cadeias de largura fixa.
Estabelece uma convenção que faz sentido e é facilmente aplicada. Eu posso escrever um carregador de esquema em um idioma para gerar código a partir desta convenção.
Preciso de um exemplo de onde eu possa fazer isso,
Abreviações de estado de duas letras, embora, como essa lista possa ser enumerada, eu normalmente o faça com um ENUM.
Observe que algumas pessoas podem se sentir desconfortáveis com a incongruência das mensagens de erro nos dois lados do limite, mas isso não me incomoda
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)
Contraste com varchar
Além disso, acho que a sugestão acima se encaixa muito bem com uma convenção de quase sempre usotext . Você pergunta sobre varchar(n)também. Eu nunca uso isso . Pelo menos, não me lembro da última vez que usei varchar(n).
Se uma especificação tem um campo de largura estática em que eu confio, eu uso char(n),
Caso contrário, eu uso o textque é efetivamente varchar(sem limite)
Se eu encontrasse uma especificação que tivesse chaves de texto de comprimento variável que fossem significativas e que eu confiasse em ter um comprimento máximo constante, eu usaria varchar(n) também . No entanto, não consigo pensar em nada que se encaixe nesse critério.
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*
Oráculo
SQL>createtable x ( y char(2));Table created.
SQL>insertinto x values('Y');1row created.
SQL>select'*'|| y ||'*'from x;'*'|----*Y *
Concordo com tudo o que foi dito por a_horse_with_no_name, e geralmente concordo com os conselhos de comentários de Erwin:
Metadados
Com uma pequena exceção, a única vez que uso
char()
é quando quero que os metadados digam que DEVE ter caracteres x. Embora eu saiba quechar()
apenas reclame se a entrada estiver acima do limite, frequentemente protegerei contra subidas devido a umaCHECK
restrição. Por exemplo,Eu faço isso por alguns motivos,
char(x)
às vezes é inferido com carregadores de esquema como sendo uma coluna de largura fixa. Isso pode fazer a diferença em um idioma otimizado para cadeias de largura fixa.Preciso de um exemplo de onde eu possa fazer isso,
ENUM
.Sobre erros
Observe que algumas pessoas podem se sentir desconfortáveis com a incongruência das mensagens de erro nos dois lados do limite, mas isso não me incomoda
Contraste com
varchar
Além disso, acho que a sugestão acima se encaixa muito bem com uma convenção de quase sempre uso
text
. Você pergunta sobrevarchar(n)
também. Eu nunca uso isso . Pelo menos, não me lembro da última vez que useivarchar(n)
.char(n)
,text
que é efetivamentevarchar
(sem limite)Se eu encontrasse uma especificação que tivesse chaves de texto de comprimento variável que fossem significativas e que eu confiasse em ter um comprimento máximo constante, eu usaria
varchar(n)
também . No entanto, não consigo pensar em nada que se encaixe nesse critério.Notas Adicionais
char
aqui não deve ser confundido com o"char"
tipo de um byte e possui sólidos benefícios de desempenho e economia de espaço.Perguntas e Respostas relacionadas:
fonte
Postgresql
Oráculo
O Postgresql não preenchia com espaços.
fonte
SELECT pg_column_size(y) FROM x;
Achei isso mais útil e uma explicação rápida de 3 linhas:
fonte