Usando texto MAX ou mais específico, tipo menor

22

Alguém estava revisando meu código DDL para criar tabelas e sugeriu, quando viram que vi VARCHAR(256)campos usando texto, espero ser bem pequeno, como um primeiro nome ou qualquer outra coisa, que eu sempre deveria usar VARCHAR(MAX)e vincular Por que usar qualquer coisa, exceto varchar (max ) . Eu li, mas parecia datado, pois estava focado em 2005 e não parecia oferecer nenhuma justificativa real para alocar potencialmente até 2 GB por linha em todos os campos de texto.

Do ponto de vista de desempenho, armazenamento etc., como decidir sobre o uso VARCHAR(MAX)ou um tipo menor e mais específico para versões modernas do SQL Server? (por exemplo, 2008, 2012, 2014)

Phrancis
fonte

Respostas:

31

Devo sempre usar (n)varchar(max)para colunas de texto?

Não.

Para o SQL Server, os maxtipos de dados devem ser especificados apenas quando não houver alternativa. Em vez disso, deve-se escolher o tipo de base correto ( varcharou nvarchar) e especificar um comprimento máximo explícito adequado aos dados a serem armazenados.

O armazenamento físico é idêntico, independentemente de a coluna ser digitada como varchar(n)ou varchar(max), portanto, essa não é a preocupação.

Os motivos para não escolher em (n)varchar(max)qualquer lugar giram em torno de recursos, qualidade do plano e desempenho.

Uma lista exaustiva provavelmente não é prática, mas, entre outras coisas, maxcolunas:

Recursos

  • Exigir uma restrição separada para impor um comprimento máximo
  • Não pode ser uma chave em um índice (portanto, também não há restrições exclusivas)
  • Pode impedir DDL online (incluindo recriações de índice e adição de uma nova coluna não nula)
  • Geralmente não são suportados para recursos 'mais recentes', por exemplo, columnstore
  • Consulte a documentação do produto para obter recursos e limitações mais específicos. O padrão geral é que existem limitações e restrições embaraçosas em torno maxdos tipos de dados. Nem todas as limitações e efeitos colaterais estão documentados.

atuação

  • Exigir tratamento especial no mecanismo de execução, para considerar o tamanho potencialmente muito grande. Normalmente, isso envolve o uso de um caminho de código menos eficiente, com uma interface de streaming
  • Pode ter conseqüências imprevistas semelhantes para código externo (e outros componentes do SQL Server como SSIS), que também devem estar preparados para manipular dados de tamanho de até 2 GB
  • Supõe-se ter 4000 bytes de largura nos cálculos de concessão de memória. É provável que isso leve a reserva de memória excessiva, o que limita a simultaneidade e empurra valiosas páginas de índice e dados da memória cache
  • Desative várias otimizações de desempenho importantes
  • Pode prolongar a duração do bloqueio
  • Pode impedir que o otimizador escolha um plano de busca (não dinâmico)
  • Impedir a inserção de filtros nas varreduras e buscar como um resíduo
  • Pode aumentar a pressão e a contenção do tempdb (dependente da versão), pois também é provável que variáveis ​​e parâmetros sejam digitados maxpara corresponder às definições da coluna

Em resumo, existem tantos efeitos colaterais sutis (e indesejáveis) do uso desnecessário do maxespecificador que não faz sentido fazer isso. A menor 'conveniência' de usar uma única declaração não é um tipo de compensação.

Avalie cada tipo no contexto, use o tipo de base correto ( varcharou nvarchar) e um comprimento explícito sensível.

Leitura adicional:

Paul White diz que a GoFundMonica
fonte
8

Isso parecerá uma resposta paranóica, mas não há apenas considerações de armazenamento e desempenho.

O próprio banco de dados não controla seus clientes, e não se pode supor que os clientes sempre insiram com segurança a entrada do usuário - mesmo que um banco de dados seja projetado para ser usado apenas com um aplicativo .net que use o Entity Framework para encapsular transações e garantir consultas parametrizadas são sistematicamente usados, você não pode saber que sempre será o caso.

Eu não saberia exatamente como fazer isso, mas criando todos os campos de texto varchar(max), se um cliente tiver problemas com Bobby Tables e / ou os parâmetros de seus procedimentos armazenados também varchar(max), você estará facilitando a criação de um invasor. um valor de parâmetro válido, mas habilmente mau, que pode fazer coisas que os clientes não deveriam estar fazendo - seja o que for.

Ao limitar o tamanho ao que você realmente precisa, você não está se protegendo desses ataques inteligentes (nem tenho certeza do que realmente se chama, lembro-me de ler sobre isso há algum tempo), mas você não está dizendo " vá em frente, tente me dar um script de 2 GB para executar "também.

Mathieu Guindon
fonte
O que é chamado é provavelmente "injeção" ("injeção SQL", mais especificamente).
Andriy M
@AndriyM sim, por algum motivo eu estava pensando em ataques de truncamento de SQL (a MS parece ter retirado o link que eu havia marcado), mas isso é basicamente explorar varchar(not-max)parâmetros, então eu meio que enfiei um pé na minha boca aqui. Mas sim, a injeção de SQL seria aplicável aqui. Talvez eu deva reformular esta resposta um pouco.
Mathieu Guindon