Práticas recomendadas para o comprimento da coluna varchar do SQL [fechado]


288

Toda vez que é configurada uma nova tabela SQL ou adiciona uma nova varcharcoluna a uma tabela existente, estou me perguntando uma coisa: qual é o melhor valor para o length.

Então, digamos, você tem uma coluna chamada namedo tipo varchar. Então, você tem que escolher o comprimento. Não consigo pensar em um nome> 20 caracteres, mas você nunca saberá. Mas, em vez de usar 20, sempre arredondo para o próximo número 2 ^ n. Nesse caso, eu escolheria 32 como o comprimento. Faço isso porque, do ponto de vista de um cientista da computação, um número 2 ^ n evenme parece mais do que outros números e estou assumindo que a arquitetura abaixo pode lidar com esses números um pouco melhor do que outros.

Por outro lado, o servidor MSSQL, por exemplo, define o valor padrão do comprimento como 50, quando você escolhe criar uma coluna varchar. Isso me faz pensar sobre isso. Por que 50? é apenas um número aleatório, ou baseado no comprimento médio da coluna, ou o quê?

Também pode ser - ou provavelmente é - que diferentes implementações de servidores SQL (como MySQL, MSSQL, Postgres, ...) tenham melhores valores de comprimento de coluna diferentes.

Respostas:


238

Nenhum DBMS que conheço possui qualquer "otimização" que faça VARCHARcom que um 2^ncomprimento tenha um desempenho melhor do que um com um maxcomprimento que não seja uma potência 2.

Acho que as primeiras versões do SQL Server tratavam um VARCHARcomprimento 255 diferente daquele que possuía um comprimento máximo maior. Não sei se ainda é esse o caso.

Para quase todos os DBMS, o armazenamento real necessário é determinado apenas pelo número de caracteres que você coloca nele, não pelo maxcomprimento definido. Portanto, do ponto de vista do armazenamento (e provavelmente também do desempenho), não faz diferença se você declara uma coluna como VARCHAR(100)ou VARCHAR(500).

Você deve ver o maxcomprimento fornecido para uma VARCHARcoluna como um tipo de restrição (ou regra de negócios) em vez de algo técnico / físico.

Para o PostgreSQL, a melhor configuração é usar textsem restrição de comprimento e CHECK CONSTRAINTque limite o número de caracteres para o que sua empresa exigir.

Se esse requisito mudar, alterar a restrição de verificação é muito mais rápido do que alterar a tabela (porque a tabela não precisa ser reescrita)

O mesmo pode ser aplicado para Oracle e outros - no Oracle, em VARCHAR(4000)vez disso text.

Não sei se há uma diferença de armazenamento físico entre VARCHAR(max)e, por exemplo, VARCHAR(500)no SQL Server. Mas, aparentemente, há um impacto no desempenho ao usar varchar(max)em comparação com varchar(8000).

Veja este link (postado por Erwin Brandstetter como um comentário)

Edit 22-09-2013

Em relação ao comentário de bigown:

Em Postgres versões antes 9.2 (que não estava disponível quando eu escrevi a resposta inicial) uma alteração na definição de coluna fez reescrever toda a tabela, ver, por exemplo aqui . Desde 9.2, esse não é mais o caso, e um teste rápido confirmou que o aumento do tamanho da coluna de uma tabela com 1,2 milhão de linhas levou apenas 0,5 segundos.

Para a Oracle, isso também parece verdadeiro, a julgar pelo tempo necessário para alterar a varcharcoluna de uma grande tabela . Mas não encontrei nenhuma referência para isso.

Para o MySQL, o manual diz " Na maioria dos casos, ALTER TABLEfaz uma cópia temporária da tabela original ". E meus próprios testes confirmam que: executar um ALTER TABLEem uma tabela com 1,2 milhão de linhas (o mesmo que no meu teste com o Postgres) para aumentar o tamanho de uma coluna levou 1,5 minutos. No MySQL, no entanto, você não pode usar a "solução alternativa" para usar uma restrição de verificação para limitar o número de caracteres em uma coluna.

Para o SQL Server, não consegui encontrar uma declaração clara sobre isso, mas o tempo de execução para aumentar o tamanho de uma varcharcoluna (novamente a tabela de 1,2 milhão de linhas acima) indica que nenhuma reescrita ocorre.

Editar 2017-01-24

Parece que eu estava (pelo menos parcialmente) errado sobre o SQL Server. Veja esta resposta de Aaron Bertrand que mostra que o comprimento declarado de uma nvarcharou varcharcolunas faz uma enorme diferença para o desempenho.


34
Na verdade, há uma diferença entre VARCHAR (255) e VARCHAR (500), mesmo se você colocar 1 caractere dentro dessa coluna. O valor acrescentado no final da linha será um número inteiro que armazena qual é o tamanho real dos dados armazenados. No caso de VARCHAR (255), será um número inteiro de 1 byte. No caso de VARCHAR (500), serão 2 bytes. é uma pequena diferença, mas é preciso estar ciente disso. Não tenho dados à mão sobre como isso pode afetar o desempenho, mas presumo que seja tão pequeno que não valha a pena pesquisar.
NB

1
@ NB: é o que eu estava me referindo para o valor "mágico" 255 do SQL Server. Obrigado pelo esclarecimento.
a_horse_with_no_name

4
@NB A que RDBMS você está se referindo? Servidor SQL? Há um efeito no desempenho. [N] VARCHAR (máx) executa um pouco mais lento que [N] VARCHAR (n). Recentemente, fui encaminhado para este site . O mesmo não se aplica ao PostgreSQL, pelo que sei.
Erwin Brandstetter

@ ErwinBrandstetter: Obrigado pelo link. Parece que varchar(max)é provavelmente mais parecido com o da OracleCLOB
a_horse_with_no_name 28/11

1
Alterar o comprimento do varchar não reescreve a tabela. Apenas verifique o comprimento da restrição em toda a tabela exatamente como CHECK CONSTRAINT. Se você aumentar o comprimento, não há nada a fazer, apenas a próxima inserção ou atualizações aceitarão um comprimento maior. Se você diminuir o comprimento e todas as linhas passarem pela nova restrição menor, a Pg não executará nenhuma outra ação além de permitir que as próximas inserções ou atualizações gravem apenas o novo comprimento.
Maniero 22/09

69

VARCHAR(255)e VARCHAR(2)ocupe exatamente a mesma quantidade de espaço em disco! Portanto, o único motivo para limitá-lo é se você tem uma necessidade específica de que ele seja menor. Caso contrário, faça todos eles 255.

Especificamente, ao fazer a classificação, uma coluna maior ocupa mais espaço; portanto, se isso prejudica o desempenho, você precisa se preocupar com isso e reduzi-lo. Mas se você selecionar apenas uma linha dessa tabela, poderá fazê-las todas 255 e isso não importa.

Veja: Quais são os tamanhos ótimos de varchar para o MySQL?


7
Por que não fazê-los todos VARCHAR(MAX)? Espaço não é a única consideração ao modelar um banco de dados. O domínio que você está modelando deve direcionar tipos e tamanhos de dados.
Oded

6
@Oded VARCHAR(MAX)não é o mesmo que varchar(255)ou varchar(65535)- varchar max é um tipo de tipo de textdados. E ao seu ponto - se ele soubesse qual o "domínio que ele estava modelando", ele não faria essa pergunta. Claramente, ele não sabe o tamanho dos dados e estou assegurando-lhe que fazê-lo em tamanho real não prejudica nada.
Ariel

4
@ Ariel: Existem questões e limitações nos índices a serem considerados também. Você não pode ter um (a,b,c,d)índice quando todas as quatro colunas estiverem VARCHAR(255).
ypercubeᵀᴹ

@ypercube Isso é verdade, se suas colunas precisam de um índice, você precisa ter mais cuidado com os tamanhos. Como a maioria das colunas não precisa de um índice, na maioria das vezes você não precisa se preocupar com isso.
Ariel #

Eu acho que se soubermos o valor exato, prefiro usar char. Enquanto isso, se ainda estiver preditora i usar varchar e mantê-255, pois é a alocação de memória dinâmica para que você não se preocupe com o tamanho que serão tomadas
Faris Rayhan

54

Sempre que configuro uma nova tabela SQL, sinto da mesma maneira que 2 ^ n é mais "par" ... mas, para resumir as respostas aqui, não há impacto significativo no espaço de armazenamento simplesmente definindo varchar (2 ^ n) ou mesmo varchar (MAX).

Dito isso, você ainda deve antecipar as implicações potenciais sobre armazenamento e desempenho ao definir um limite alto de varchar (). Por exemplo, digamos que você crie uma coluna varchar (MAX) para armazenar descrições de produtos com indexação de texto completo. Se 99% das descrições tiverem apenas 500 caracteres e, de repente, você conseguir alguém que substitua as descrições por artigos da wikipedia, você poderá perceber acertos significativos inesperados de armazenamento e desempenho.

Outra coisa a considerar de Bill Karwin :

Há um possível impacto no desempenho: no MySQL, tabelas temporárias e tabelas MEMORY armazenam uma coluna VARCHAR como uma coluna de comprimento fixo, preenchida em seu comprimento máximo. Se você criar colunas VARCHAR muito maiores que o maior tamanho necessário, consumirá mais memória do que precisa. Isso afeta a eficiência do cache, a velocidade de classificação etc.

Basicamente, basta apresentar restrições comerciais razoáveis ​​e erros em um tamanho um pouco maior. Como @onedaywhen apontou, os nomes de família no Reino Unido geralmente têm entre 1 e 35 caracteres. Se você decidir fazer o varchar (64), não vai machucar nada ... a menos que esteja armazenando o nome de família desse cara com 666 caracteres. Nesse caso, talvez varchar (1028) faça mais sentido.

E, caso seja útil, eis como varchar 2 ^ 5 a 2 ^ 10 pode parecer se preenchido:

varchar(32)     Lorem ipsum dolor sit amet amet.

varchar(64)     Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie

varchar(128)    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie
                vestibulum massa. Nullam dignissim elementum molestie. Vehiculas

varchar(256)    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie
                vestibulum massa. Nullam dignissim elementum molestie. Vehiculas
                velit metus, sit amet tristique purus condimentum eleifend. Quis
                que mollis magna vel massa malesuada bibendum. Proinde tincidunt

varchar(512)    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie
                vestibulum massa. Nullam dignissim elementum molestie. Vehiculas
                velit metus, sit amet tristique purus condimentum eleifend. Quis
                que mollis magna vel massa malesuada bibendum. Proinde tincidunt
                dolor tellus, sit amet porta neque varius vitae. Seduse molestie
                lacus id lacinia tempus. Vestibulum accumsan facilisis lorem, et
                mollis diam pretium gravida. In facilisis vitae tortor id vulput
                ate. Proin ornare arcu in sollicitudin pharetra. Crasti molestie

varchar(1024)   Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie
                vestibulum massa. Nullam dignissim elementum molestie. Vehiculas
                velit metus, sit amet tristique purus condimentum eleifend. Quis
                que mollis magna vel massa malesuada bibendum. Proinde tincidunt
                dolor tellus, sit amet porta neque varius vitae. Seduse molestie
                lacus id lacinia tempus. Vestibulum accumsan facilisis lorem, et
                mollis diam pretium gravida. In facilisis vitae tortor id vulput
                ate. Proin ornare arcu in sollicitudin pharetra. Crasti molestie
                dapibus leo lobortis eleifend. Vivamus vitae diam turpis. Vivamu
                nec tristique magna, vel tincidunt diam. Maecenas elementum semi
                quam. In ut est porttitor, sagittis nulla id, fermentum turpist.
                Curabitur pretium nibh a imperdiet cursus. Sed at vulputate este
                proin fermentum pretium justo, ac malesuada eros et Pellentesque
                vulputate hendrerit molestie. Aenean imperdiet a enim at finibus
                fusce ut ullamcorper risus, a cursus massa. Nunc non dapibus vel
                Lorem ipsum dolor sit amet, consectetur Praesent ut ultrices sit

31

O melhor valor é o correto para os dados, conforme definido no domínio subjacente.

Para alguns domínios, VARCHAR(10)é adequado para o Nameatributo, para outros domínios VARCHAR(255)pode ser a melhor opção.


15

Adicionando à resposta de a_horse_with_no_name, você pode encontrar o seguinte de interesse ...

não faz diferença se você declara uma coluna como VARCHAR (100) ou VACHAR (500).

-- try to create a table with max varchar length
drop table if exists foo;
create table foo(name varchar(65535) not null)engine=innodb;

MySQL Database Error: Row size too large.

-- try to create a table with max varchar length - 2 bytes for the length
drop table if exists foo;
create table foo(name varchar(65533) not null)engine=innodb;

Executed Successfully

-- try to create a table with max varchar length with nullable field
drop table if exists foo;
create table foo(name varchar(65533))engine=innodb;

MySQL Database Error: Row size too large.

-- try to create a table with max varchar length with nullable field
drop table if exists foo;
create table foo(name varchar(65532))engine=innodb;

Executed Successfully

Não se esqueça do byte de comprimento e do byte nulo;

name varchar(100) not null terá 1 byte (comprimento) + até 100 caracteres (latin1)

name varchar(500) not null terá 2 bytes (comprimento) + até 500 caracteres (latin1)

name varchar(65533) not null terá 2 bytes (comprimento) + até 65533 caracteres (latin1)

name varchar(65532) terá 2 bytes (comprimento) + até 65532 caracteres (latin1) + 1 byte nulo

Espero que isto ajude :)


Você está usando MySQL, e a pergunta é sobre MSSQL
Bogdan Mart


3

Não verifiquei isso recentemente, mas sei no passado com a Oracle que o driver JDBC reservaria um pedaço de memória durante a execução da consulta para manter o conjunto de resultados retornando. O tamanho do pedaço de memória depende das definições da coluna e do tamanho da busca. Portanto, o comprimento das colunas varchar2 afeta a quantidade de memória reservada. Isso causou sérios problemas de desempenho para mim anos atrás, pois sempre usamos varchar2 (4000) (o máximo da época) e a coleta de lixo era muito menos eficiente do que é hoje.


-2

De certa forma, você está certo, embora algo menor que 2 ^ 8 caracteres ainda seja registrado como um byte de dados.

Se você considerar o caractere base que deixa qualquer coisa com um VARCHAR <255 como consumindo a mesma quantidade de espaço.

255 é uma boa definição de linha de base, a menos que você particularmente queira reduzir a entrada excessiva.


" embora algo menor que 2 ^ 8 caracteres ainda seja registrado como um byte de dados " - errado. O banco de dados armazena apenas quantos caracteres são fornecidos em um tipo VARCHAR. Nenhum espaço é "registrado", reservado ou inicializado ao declarar uma coluna.
a_horse_with_no_name 31/07/19
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.