Percebo que CHAR é recomendado se todos os meus valores tiverem largura fixa. Mas e daí? Por que não escolher VARCHAR para todos os campos de texto apenas por segurança?
Percebo que CHAR é recomendado se todos os meus valores tiverem largura fixa. Mas e daí? Por que não escolher VARCHAR para todos os campos de texto apenas por segurança?
Respostas:
Geralmente escolha CHAR se todas as linhas tiverem o mesmo comprimento . Escolha VARCHAR quando o comprimento variar significativamente. CHAR também pode ser um pouco mais rápido, porque todas as linhas têm o mesmo comprimento.
Varia de acordo com a implementação do banco de dados, mas geralmente o VARCHAR usa um ou dois bytes de armazenamento (para comprimento ou finalização) além dos dados reais. Então (supondo que você esteja usando um conjunto de caracteres de um byte) armazenando a palavra "FooBar"
A linha inferior é que CHAR pode ser mais rápida e mais eficiente em termos de espaço para dados de aproximadamente o mesmo comprimento (diferença de comprimento de dois caracteres).
Nota : O Microsoft SQL possui 2 bytes de sobrecarga para um VARCHAR. Isso pode variar de DB para DB, mas geralmente há pelo menos 1 byte de sobrecarga necessário para indicar o comprimento ou o EOL em um VARCHAR.
Conforme apontado por Gaven nos comentários, se você estiver usando um conjunto de caracteres de vários bytes e comprimento variável como UTF8, o CHAR armazenará o número máximo de bytes necessários para armazenar o número de caracteres. Portanto, se o UTF8 precisar no máximo de 3 bytes para armazenar um caractere, CHAR (6) será corrigido em 18 bytes, mesmo se apenas armazenar caracteres latin1. Portanto, neste caso, o VARCHAR se torna uma escolha muito melhor.
Se você estiver trabalhando comigo e trabalhando com a Oracle, eu provavelmente o faria usar varchar
em quase todas as circunstâncias. A suposição de que char
usa menos poder de processamento do que varchar
pode ser verdade ... por enquanto ... mas os mecanismos de banco de dados melhoram com o tempo e esse tipo de regra geral cria um "mito" futuro.
Outra coisa: nunca vi um problema de desempenho porque alguém decidiu seguir em frente varchar
. Você utilizará muito melhor seu tempo escrevendo código bom (menos chamadas para o banco de dados) e SQL eficiente (como funcionam os índices, como o otimizador toma decisões, por que é exists
mais rápido do que o in
habitual ...).
Pensamento final: vi todos os tipos de problemas com o uso de CHAR
pessoas que procuravam '' quando deveriam procurar '' ou pessoas que procuravam 'FOO' quando procuravam 'FOO (muitos espaços aqui)' , ou pessoas que não cortam os espaços em branco à direita ou erros com o Powerbuilder adicionando até 2000 espaços em branco ao valor que ele retorna de um procedimento Oracle.
Além dos benefícios de desempenho, CHAR
pode ser usado para indicar que todos os valores devem ter o mesmo comprimento, por exemplo, uma coluna para abreviações de estados dos EUA.
CHAR
, tenha certeza de que o seu restrição restringe o preenchimento.
Char é um pouco mais rápido; portanto, se você tiver uma coluna que sabe que terá um determinado comprimento, use char. Por exemplo, armazenando (M) ale / (F) emale / (U) conhecido por sexo ou 2 caracteres para um estado dos EUA.
NChar ou Char têm um desempenho melhor que suas alternativas var?
Ótima pergunta. A resposta simples é sim em certas situações. Vamos ver se isso pode ser explicado.
Obviamente, todos sabemos que se eu criar uma tabela com uma coluna de varchar (255) (vamos chamar essa coluna de myColumn) e inserir um milhão de linhas, mas colocar apenas alguns caracteres em myColumn para cada linha, a tabela será muito menor (no geral número de páginas de dados necessárias pelo mecanismo de armazenamento) do que se eu tivesse criado myColumn como char (255). Sempre que eu fizer uma operação (DML) nessa tabela e solicitar várias linhas, será mais rápido quando myColumn for varchar, porque não preciso mover todos esses espaços "extras" no final. Mova, como quando o SQL Server faz classificações internas, como durante uma operação distinta ou de união, ou se escolhe uma mesclagem durante seu plano de consulta, etc.
Mas há alguma sobrecarga no uso de varchar. O SQL Server deve usar um indicador de dois bytes (sobrecarga) para, em cada linha, saber quantos bytes myColumn da linha específica possui. Não são os 2 bytes extras que apresentam o problema, é a necessidade de "decodificar" o comprimento dos dados em myColumn em todas as linhas.
Nas minhas experiências, faz mais sentido usar char em vez de varchar em colunas às quais as consultas serão unidas. Por exemplo, a chave primária de uma tabela ou alguma outra coluna que será indexada. CustomerNumber em uma tabela demográfica, ou CodeID em uma tabela de decodificação, ou talvez OrderNumber em uma tabela de pedidos. Ao usar char, o mecanismo de consulta pode executar a junção mais rapidamente, porque pode fazer aritmética direta com ponteiros (deterministicamente), em vez de precisar mover os ponteiros por uma quantidade variável de bytes enquanto lê as páginas. Eu sei que posso ter te perdido nessa última frase. As junções no SQL Server são baseadas na idéia de "predicados". Um predicado é uma condição. Por exemplo, myColumn = 1 ou OrderNumber <500.
Portanto, se o SQL Server estiver executando uma instrução DML e os predicados ou "chaves" que estão sendo unidos tiverem um comprimento fixo (caractere), o mecanismo de consulta não precisará fazer tanto trabalho para corresponder linhas de uma tabela a linhas de outra mesa. Ele não precisará descobrir quanto tempo os dados estão na linha e, em seguida, descer a string para encontrar o final. Tudo isso leva tempo.
Agora, lembre-se de que isso pode ser facilmente mal implementado. Eu vi char usado para campos de chave primária em sistemas online. A largura deve ser mantida pequena, isto é, char (15) ou algo razoável. E funciona melhor em sistemas on-line, porque você geralmente está recuperando ou ampliando apenas um pequeno número de linhas; portanto, ter que "restringir" os espaços finais que você obterá no conjunto de resultados é uma tarefa trivial, em vez de ter que juntar milhões de linhas de uma tabela para milhões de linhas em outra tabela.
Outro motivo pelo qual o CHAR faz sentido sobre o varchar em sistemas on-line é que ele reduz a divisão de páginas. Ao usar char, você está essencialmente "reservando" (e desperdiçando) esse espaço, portanto, se um usuário aparecer mais tarde e colocar mais dados nessa coluna, o SQL já alocou espaço para ele e assim por diante.
Outro motivo para usar CHAR é semelhante ao segundo motivo. Se um programador ou usuário fizer uma atualização em "lote" para milhões de linhas, adicionando alguma frase a um campo de anotação, por exemplo, você não receberá uma chamada do seu DBA no meio da noite perguntando por que as unidades estão cheias. Em outras palavras, isso leva a um crescimento mais previsível do tamanho de um banco de dados.
Portanto, essas são três maneiras pelas quais um sistema on-line (OLTP) pode se beneficiar de char sobre varchar. Eu quase nunca uso char em um cenário de armazém / análise / OLAP, porque geralmente você tem tantos dados que todas essas colunas de char podem adicionar muito espaço desperdiçado.
Lembre-se de que char pode tornar seu banco de dados muito maior, mas a maioria das ferramentas de backup possui compactação de dados; portanto, seus backups tendem a ter o mesmo tamanho que se você tivesse usado o varchar. Por exemplo, LiteSpeed ou RedGate SQL Backup.
Outro uso está nas visualizações criadas para exportar dados para um arquivo de largura fixa. Digamos que eu precise exportar alguns dados para um arquivo simples para ser lido por um mainframe. É largura fixa (não delimitada). Eu gosto de armazenar os dados na minha tabela de "teste" como varchar (consumindo menos espaço no meu banco de dados) e, em seguida, usar uma exibição para CAST tudo com seu equivalente de caractere, com o comprimento correspondente à largura da largura fixa dessa coluna . Por exemplo:
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
Isso é legal porque internamente meus dados ocupam menos espaço porque estão usando varchar. Mas quando uso DTS ou SSIS ou apenas recortar e colar do SSMS para o Bloco de Notas, posso usar a exibição e obter o número certo de espaços à direita. No DTS, costumávamos ter um recurso chamado, caramba, esqueço que acho que foi chamado de "sugerir colunas" ou algo assim. No SSIS, você não pode mais fazer isso, é necessário definir tediosamente o gerenciador de conexões de arquivos simples. Porém, como você configurou sua visualização, o SSIS pode saber a largura de cada coluna e economizar muito tempo ao criar suas tarefas de fluxo de dados.
Então, em resumo ... use varchar. Há um número muito pequeno de razões para usar char e é apenas por razões de desempenho. Se você possui um sistema com centenas de milhões de linhas, verá uma diferença perceptível se os predicados forem determinísticos (char), mas para a maioria dos sistemas que usam char estão simplesmente desperdiçando espaço.
Espero que ajude. Jeff
Há benefícios de desempenho, mas aqui está um que não foi mencionado: migração de linhas. Com char, você reserva todo o espaço com antecedência. Então, digamos que você tenha um caractere (1000) e armazene 10 caracteres, você usará todos os 1000 caracteres de espaço. Em um varchar2 (1000), você usará apenas 10 caracteres. O problema ocorre quando você modifica os dados. Digamos que você atualize a coluna para agora conter 900 caracteres. É possível que o espaço para expandir o varchar não esteja disponível no bloco atual. Nesse caso, o mecanismo do banco de dados deve migrar a linha para outro bloco e fazer um ponteiro no bloco original para a nova linha no novo bloco. Para ler esses dados, o mecanismo do banco de dados precisará agora ler 2 blocos.
Ninguém pode dizer equivocamente que varchar ou char são melhores. Há um espaço para troca de tempo e consideração sobre se os dados serão atualizados, especialmente se houver uma boa chance de que eles cresçam.
Há uma diferença entre a otimização de desempenho inicial e o uso de um tipo de regra de práticas recomendadas. Se você estiver criando novas tabelas em que sempre terá um campo de comprimento fixo, faz sentido usar CHAR, nesse caso, você deve usá-lo. Isso não é otimização antecipada, mas a implementação de uma regra de ouro (ou melhor prática).
ie - Se você possui um campo de estado de 2 letras, use CHAR (2). Se você tiver um campo com os nomes de estado reais, use VARCHAR.
Eu escolheria varchar, a menos que a coluna armazene valor fixo como o código de estado dos EUA - que tem sempre 2 caracteres e a lista de códigos de estados válidos dos EUA não muda com frequência :).
Em todos os outros casos, mesmo como armazenar uma senha com hash (que é de tamanho fixo), eu escolheria varchar.
Why - char type column sempre é preenchida com espaços, o que faz com que a coluna my_column seja definida como char (5) com o valor 'ABC' dentro da comparação:
my_column = 'ABC' -- my_column stores 'ABC ' value which is different then 'ABC'
falso.
Esse recurso pode levar a muitos bugs irritantes durante o desenvolvimento e dificulta os testes.
CHAR ocupa menos espaço de armazenamento que VARCHAR se todos os seus valores de dados nesse campo tiverem o mesmo comprimento. Agora, talvez em 2009, um banco de dados de 800 GB seja o mesmo para todos os propósitos e propósitos que um 810 GB, se você converter os VARCHARs em CHARs, mas para cadeias curtas (1 ou 2 caracteres), CHAR ainda é uma "melhor prática" do setor, eu diria.
Agora, se você observar a grande variedade de tipos de dados que a maioria dos bancos de dados fornece, mesmo para números inteiros (bit, tiny, int, bigint), há motivos para escolher um sobre o outro. Simplesmente escolher bigint sempre é realmente um pouco ignorante dos propósitos e usos do campo. Se um campo simplesmente representa a idade de uma pessoa em anos, um bigint é um exagero. Agora não é necessariamente "errado", mas não é eficiente.
Mas é um argumento interessante e, à medida que os bancos de dados melhoram com o tempo, pode-se argumentar que CHAR vs VARCHAR se tornam menos relevantes.
Eu mantenho o comentário de Jim McKeeth.
Além disso, a indexação e as varreduras completas da tabela são mais rápidas se sua tabela tiver apenas colunas CHAR. Basicamente, o otimizador será capaz de prever o tamanho de cada registro se tiver apenas colunas CHAR, enquanto ele precisa verificar o valor do tamanho de cada coluna VARCHAR.
Além disso, se você atualizar uma coluna VARCHAR para um tamanho maior que o conteúdo anterior, poderá forçar o banco de dados a reconstruir seus índices (porque você forçou o banco de dados a mover fisicamente o registro no disco). Enquanto estiver com colunas CHAR, isso nunca acontecerá.
Mas você provavelmente não se importará com o desempenho atingido, a menos que sua mesa seja enorme.
Lembre-se das sábias palavras de Djikstra. A otimização precoce do desempenho é a raiz de todo mal.
CHAR
coluna, os índices também precisam ser atualizados. Não há diferença na atualização de uma coluna VARCHAR ou CHAR a esse respeito. Pense em atualizar FOO
para BAR
.
Muitas pessoas apontaram que, se você souber o tamanho exato do valor usando CHAR, terá alguns benefícios. Porém, embora o armazenamento de estados dos EUA como CHAR (2) seja ótimo hoje, quando você recebe a mensagem das vendas de que 'Acabamos de fazer nossa primeira venda para a Austrália', você está sofrendo. Eu sempre envio para superestimar quanto tempo acho que os campos precisarão, em vez de fazer um palpite 'exato' para cobrir eventos futuros. O VARCHAR me dará mais flexibilidade nessa área.
Acho que no seu caso provavelmente não há razão para não escolher Varchar. Isso oferece flexibilidade e, como já foi mencionado por vários respondentes, o desempenho é tão agora que, exceto em circunstâncias muito específicas, os nossos mortais (em oposição aos DBAs do Google) não notam a diferença.
Uma coisa interessante que vale a pena notar quando se trata de tipos de banco de dados é o sqlite (um mini-banco de dados popular com desempenho bastante impressionante) coloca tudo no banco de dados como uma string e os tipos em tempo real.
Eu sempre uso o VarChar e geralmente o faço muito maior do que eu poderia precisar. Por exemplo. 50 para Nome, como você diz por que não apenas para estar seguro.
Eu nunca usaria caracteres. Eu tive esse debate com muitas pessoas e elas sempre trazem o clichê cansado de que char é mais rápido. Bem, eu digo, quanto mais rápido? Do que estamos falando aqui, milissegundos, segundos e, se sim, quantos? Você está me dizendo que, como alguém afirma que é alguns milissegundos mais rápido, devemos introduzir toneladas de bugs difíceis de corrigir no sistema?
Então, aqui estão alguns problemas que você encontrará:
Todos os campos serão preenchidos, para que você acabe com o código para sempre que tenha RTRIMS em todos os lugares. Isso também é um enorme desperdício de espaço em disco para campos mais longos.
Agora, digamos que você tenha o exemplo por excelência de um campo char com apenas um caractere, mas o campo é opcional. Se alguém passa uma string vazia para esse campo, ela se torna um espaço. Portanto, quando outro aplicativo / processo a consulta, eles obtêm um espaço único, se não usarem o rtrim. Tivemos documentos xml, arquivos e outros programas, exibindo apenas um espaço, em campos opcionais e quebrando coisas.
Portanto, agora você deve garantir que está passando nulos e não string vazia para o campo char. Mas esse NÃO é o uso correto de null. Aqui está o uso de null. Digamos que você obtenha um arquivo de um fornecedor
Nome | Gênero | Cidade
Bob || Los Angeles
Se o sexo não for especificado, você deve inserir Bob, sequência vazia e Los Angeles na tabela. Agora, digamos que você obtenha o arquivo e suas alterações de formato e sexo não estão mais incluídas, mas estavam no passado.
Nome | Cidade
Bob | Seattle
Bem, agora que o gênero não está incluído, eu usaria null. Varchars suportam isso sem problemas.
Char, por outro lado, é diferente. Você sempre tem que enviar nulo. Se você enviar uma string vazia, você terminará com um campo que contenha espaços.
Eu poderia continuar com todos os erros que tive que corrigir dos caracteres e em cerca de 20 anos de desenvolvimento.
Há uma pequena sobrecarga de processamento no cálculo do tamanho real necessário para um valor de coluna e na alocação de espaço para um Varchar. Portanto, se você tiver certeza de quanto tempo o valor sempre será, é melhor usar Char e evitar o acerto.
É a troca clássica de espaço versus desempenho.
No MS SQL 2005, o Varchar (ou NVarchar para idiomas que exigem dois bytes por caractere, por exemplo, chinês) tem tamanho variável. Se você adicionar à linha depois que ela foi gravada no disco rígido, os dados serão localizados em um local não-contigioso na linha original e levarão à fragmentação dos seus arquivos de dados. Isso afetará o desempenho.
Portanto, se o espaço não é um problema, Char é melhor para o desempenho, mas se você deseja manter o tamanho do banco de dados baixo, os varchars são melhores.
Fragmentação. Char reserva espaço e VarChar não. A divisão da página pode ser necessária para acomodar a atualização no varchar.
CHAR
coluna.
Em alguns bancos de dados SQL, o VARCHAR será aumentado para o tamanho máximo para otimizar os desvios. Isso é para acelerar as varreduras e os índices completos da tabela.
Por esse motivo, você não tem economia de espaço usando um VARCHAR (200) comparado a um CHAR (200)
O uso de CHAR (NCHAR) e VARCHAR (NVARCHAR) traz diferenças nas maneiras como o servidor de banco de dados armazena os dados. O primeiro introduz espaços em branco à direita; Encontrei um problema ao usá-lo com o operador LIKE nas funções SQL SERVER. Então, eu tenho que torná-lo seguro usando VARCHAR (NVARCHAR) o tempo todo.
Por exemplo, se tivermos uma tabela TEST (ID INT, Status CHAR (1)) e você escrever uma função para listar todos os registros com algum valor específico, como o seguinte:
CREATE FUNCTION List(@Status AS CHAR(1) = '')
RETURNS TABLE
AS
RETURN
SELECT * FROM TEST
WHERE Status LIKE '%' + @Status '%'
Nesta função, esperamos que, quando colocarmos o parâmetro padrão, a função retorne todas as linhas, mas, na verdade, não. Altere o tipo de dados @Status para VARCHAR para corrigir o problema.