O código EF primeiro usa nvarchar (max) para todas as strings. Isso prejudicará o desempenho da consulta?


29

Eu tenho alguns bancos de dados criados usando o 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 eu quero que o banco de dados faça; e minha pergunta é: qual penalidade vou comer ao ter essas nvarchar(max)cordas na minha mesa (veja o exemplo abaixo)?

Existem várias colunas nesta tabela específica; em C # eles são definidos da seguinte maneira:

    [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 Nome e Origem tenham entre 0 e 50 caracteres, ocasionalmente até 150. Espero que esta tabela comece muito 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 é que há um impacto no desempenho das minhas colunas Nome e Origem sendo definidas como nvarchar(max)quando eu nunca espero que elas tenham mais de 150 caracteres?


5
Parece que você precisa aplicar um [MaxLength]ou [StringLength]atributos. Alguns fatores negativos possíveis adicionais de colunas demasiado largas são mencionados na resposta de @ PaulWhite aqui
Martin Smith

3
SIM , usar em varchar(max)qualquer lugar prejudica seu desempenho - não faça isso! Use tipos de dados apropriados - use varchar(max) SOMENTE se você REALMENTE precisar de mais de 8000 caracteres! (Nunca vi tanto o nome ou o email de uma pessoa!) - Veja Qual é o sentido de usar o VARCHAR (n) mais? para mais informações
marc_s

@marc_s Ótimo link. Eu sei que isso prejudica o desempenho. Quando defino minhas próprias tabelas com SQL, uso varchar (n). Minha pergunta era mais sobre o quanto isso prejudica o desempenho (embora eu perceba como postado que não era explicitamente claro).
Nate

Respostas:


24

Itens de dados nvarchar (máx.) Maiores (acima de 8000 bytes) serão transferidos para o armazenamento de texto e exigirão E / S adicionais. Os 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 na linha, não há sobrecarga significativa no desempenho de E / S; pode haver sobrecarga adicional da CPU no processamento do tipo de dados, mas é provável que isso seja menor.

No entanto, deixar as 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, muitas vezes, os tamanhos de dados são bastante úteis para entender uma tabela de dados - por exemplo, uma coluna varchar de 50 ou 100 caracteres de largura provavelmente é uma descrição ou um campo de texto livre onde um que é (digamos) 10- É provável que 20 caracteres sejam um código. Você ficaria surpreso com o significado que muitas vezes é necessário deduzir de um banco de dados através de suposições como esta.

Trabalhar em data warehousing, sempre que não em sistemas legados com suporte insuficiente ou documentado, ter um esquema de banco de dados fácil de entender é bastante valioso. Se você pensa no banco de dados como legado do aplicativo, tente ser gentil com as pessoas que o herdarão.


18

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 nas suas variáveis ​​de string na classe do 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 de nvarchar(max).

Por exemplo, em vez de:

public string Name { get; set; }

Você pode usar:

[StringLength(50)]
public string Name { get; set; }

Você também pode forçar o tipo a ser, em varcharvez de nvarchar, se desejado, da seguinte maneira:

[Column(TypeName = "VARCHAR")]
[StringLength(50)]
public string Name { get; set; }

Origem: /programming/7341783/entity-framework-data-annotations-set-stringlength-varchar/7341920


2
Foi preciso encontrar essa resposta para descobrir que o EF Core suporta o tipo e a duração da configuração ao mesmo tempo ( varchar(50)), mas o EF 6 exige o que há nessa resposta.
Sinjai 25/01

9

Indexando a maior preocupação. Partida BOL:

Colunas que são os tipos de dados de objecto de grandes dimensões (LPP) ntext, text, varchar(max), nvarchar(max), varbinary(max), xml, ou imagepode não ser especificado como colunas de chave para um índice.

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 inseridos em um campo do que especificar o limite.


9

Sim, o comportamento EF padrão no mapeamento stringpara nvarchar(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.

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Properties<string>()
        .Configure(s => s.HasMaxLength(200).HasColumnType("varchar") );

    base.OnModelCreating(modelBuilder);
}

A substituição OnModelCreatingcomo acima mudará o mapeamento padrão de todas as strings para varchar(200).


1
Isso não funciona no EF Core 1.0
Shittu Joseph Olugbenga 15/16

the default EF behavior in mapping string to nvarchar(max) is not goodessa parece ser sua opinião generalizada. você pode explicar por que isso não é bom? Ou, você acha que a EF não é uma estrutura para aplicativos de negócios em que você precisa trabalhar com vários idiomas? Porque esse é o tipo de coluna desejado para lidar com vários idiomas no banco de dados.
Matthias Burger

1
O @MatthiasBurger nvarchar (max) é péssimo para o desempenho, especialmente em um ambiente replicado. Não é uma opinião generalizada, é um fato bem conhecido.
User2966445

@ user2966445 desculpe, acho que houve um mal-entendido :) claro, maxé horrível. Mas se você quiser lidar com vários idiomas (e seus diferentes conjuntos de caracteres), precisará usar nvarcharEstou errado?
Matthias Burger

@MatthiasBurger Está correto, use nvarchar para diferentes conjuntos de caracteres, mas todo este post é sobre desempenho e tamanho de campo, não o uso de nvarchar vs. varchar.
User2966445
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.