Tenho alguns bancos de dados criados usando Entity Framework Code First; os aplicativos estão funcionando e, em geral, estou muito feliz com o que o Code First me permite fazer. Eu sou um programador primeiro, e um DBA segundo, por necessidade. Estou lendo sobre DataAttributes para descrever melhor em C# o que quero que o banco de dados faça; e minha pergunta é: que penalidade estarei comendo por ter essas nvarchar(max)
strings na minha tabela (veja o exemplo abaixo)?
Existem várias colunas nesta tabela em particular; em C# eles são definidos como tal:
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public string Name { get; set; }
public string Message { get; set; }
public string Source { get; set; }
public DateTime Generated { get; set; }
public DateTime Written { get; set; }
Espero consultar e/ou classificar com base em Nome, Origem, Gerado e Escrito. Espero que Name e Source estejam no comprimento de 0-50 caracteres, ocasionalmente até 150. Espero que esta tabela comece bem pequena (<100k linhas), mas cresça significativamente ao longo do tempo (>1m linhas). Obviamente, a mensagem pode ser pequena ou grande e provavelmente não será consultada.
O que eu quero saber, há um impacto de desempenho para minhas colunas Name e Source sendo definidas como nvarchar(max)
quando eu nunca espero que elas tenham mais de 150 caracteres?
Itens de dados nvarchar (max) maiores (mais de 8.000 bytes ou mais) se espalharão para o armazenamento de texto e exigirão E/S adicional. Itens menores serão armazenados em linha. Existem opções que controlam esse comportamento - consulte este artigo do MSDN para obter mais detalhes.
Se armazenado em linha, não há sobrecarga de desempenho de E/S significativa; pode haver sobrecarga de CPU adicional no processamento do tipo de dados, mas isso provavelmente será menor.
No entanto, deixar colunas nvarchar (max) espalhadas pelo banco de dados onde elas não são necessárias é uma forma bastante ruim. Ele tem alguma sobrecarga de desempenho e geralmente os tamanhos de dados são bastante úteis para entender uma tabela de dados - por exemplo, uma coluna varchar de 50 ou 100 caracteres provavelmente é uma descrição ou um campo de texto livre onde um que é (digamos) 10- 20 caracteres ling é provável que seja um código. Você ficaria surpreso com a quantidade de significado que muitas vezes é preciso inferir de um banco de dados por meio de suposições como essa.
Trabalhar em data warehousing, muitas vezes em sistemas legados mal suportados ou documentados, ter um esquema de banco de dados fácil de entender é muito valioso. Se você pensa no banco de dados como o legado do aplicativo, tente ser gentil com as pessoas que irão herdá-lo de você.
Embora isso não responda à sua pergunta específica, pode impedir que você precise fazer a pergunta em primeiro lugar: é possível definir um comprimento em suas variáveis de string em sua classe de modelo C#, o que fará com que o Entity Framework gere SQL que usa um tipo nvarchar de comprimento fixo (por exemplo
nvarchar(50)
, ), em vez denvarchar(max)
.Por exemplo, em vez de:
Você pode usar:
Você também pode forçar o tipo a ser
varchar
em vez denvarchar
, se desejar, da seguinte maneira:Fonte: https://stackoverflow.com/questions/7341783/entity-framework-data-annotations-set-stringlength-varchar/7341920
Indexação a maior preocupação. De BOL:
Se você não conseguir indexar corretamente, terá consultas lentas. E do ponto de vista da integridade dos dados, ter
nvarchar(max)
permitirá que mais dados ruins sejam colocados em um campo do que seria especificar o limite.Sim, o comportamento padrão do EF no mapeamento
string
paranvarchar(max)
não é bom. No EF 6, você pode adicionar sua própria convenção personalizada para substituir esse comportamento pelo seu próprio mapeamento padrão preferido.A substituição
OnModelCreating
como acima alterará o mapeamento padrão de todas as strings paravarchar(200)
.