Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Os índices são um conceito comum em muitos armazenamentos de dados. Embora sua implementação no armazenamento de dados possa variar, eles são usados para tornar as pesquisas baseadas em uma coluna (ou conjunto de colunas) mais eficientes. Consulte a seção índices na documentação de desempenho para obter mais informações sobre o bom uso do índice.
Você pode especificar um índice em uma coluna da seguinte maneira:
[Index(nameof(Url))]
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
}
Observação
Por convenção, um índice é criado em cada propriedade (ou conjunto de propriedades) que são usadas como uma chave estrangeira.
Índice composto
Um índice também pode abranger mais de uma coluna:
[Index(nameof(FirstName), nameof(LastName))]
public class Person
{
public int PersonId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
Os índices em várias colunas, também conhecidos como índices compostos, aceleram as consultas que filtram as colunas do índice, mas também as consultas que filtram apenas as primeiras colunas cobertas pelo índice. Consulte os documentos de desempenho para obter mais informações.
Exclusividade do índice
Por padrão, os índices não são exclusivos: várias linhas podem ter o(s) mesmo(s) valor(es) para o conjunto de colunas do índice. Você pode tornar um índice exclusivo da seguinte maneira:
[Index(nameof(Url), IsUnique = true)]
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
}
A tentativa de inserir mais de uma entidade com os mesmos valores para o conjunto de colunas do índice resultará em uma exceção.
Ordem de classificação do índice
Na maioria dos bancos de dados, cada coluna coberta por um índice pode ser ascendente ou descendente. Para índices que cobrem apenas uma coluna, isso normalmente não importa: o banco de dados pode percorrer o índice em ordem inversa, conforme necessário. No entanto, para índices compostos, a ordenação pode ser crucial para um bom desempenho e pode significar a diferença entre um índice ser usado por uma consulta ou não. Em geral, as ordens de classificação das colunas de índice devem corresponder às especificadas na ORDER BY cláusula da consulta.
A ordem de classificação do índice é crescente por padrão. Você pode fazer com que todas as colunas tenham ordem decrescente da seguinte maneira:
[Index(nameof(Url), nameof(Rating), AllDescending = true)]
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
public int Rating { get; set; }
}
Você também pode especificar a ordem de classificação coluna por coluna da seguinte maneira:
[Index(nameof(Url), nameof(Rating), IsDescending = new[] { false, true })]
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
public int Rating { get; set; }
}
Nomenclatura de índices e vários índices
Por convenção, os índices criados em um banco de dados relacional são nomeados IX_<type name>_<property name>. Para índices compostos, <property name> torna-se uma lista de nomes de propriedades separados por sublinhados.
Você pode definir o nome do índice criado no banco de dados:
[Index(nameof(Url), Name = "Index_Url")]
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
}
Observe que, se você chamar HasIndex mais de uma vez no mesmo conjunto de propriedades, isso continuará a configurar um único índice em vez de criar um novo:
modelBuilder.Entity<Person>()
.HasIndex(p => new { p.FirstName, p.LastName })
.HasDatabaseName("IX_Names_Ascending");
modelBuilder.Entity<Person>()
.HasIndex(p => new { p.FirstName, p.LastName })
.HasDatabaseName("IX_Names_Descending")
.IsDescending();
Como a segunda HasIndex chamada substitui a primeira, isso cria apenas um único índice descendente. Isso pode ser útil para configurar ainda mais um índice que foi criado por convenção.
Para criar vários índices sobre o mesmo conjunto de propriedades, passe um nome para o HasIndex, que será usado para identificar o índice no modelo EF e distingui-lo de outros índices sobre as mesmas propriedades:
modelBuilder.Entity<Person>()
.HasIndex(p => new { p.FirstName, p.LastName }, "IX_Names_Ascending");
modelBuilder.Entity<Person>()
.HasIndex(p => new { p.FirstName, p.LastName }, "IX_Names_Descending")
.IsDescending();
Observe que esse nome também é usado como padrão para o nome do banco de dados, portanto, não é necessário chamar HasDatabaseName explicitamente.
Filtro de índice
Alguns bancos de dados relacionais permitem especificar um índice filtrado ou parcial. Isso permite indexar apenas um subconjunto dos valores de uma coluna, reduzindo o tamanho do índice e melhorando o desempenho e o uso de espaço em disco. Para obter mais informações sobre índices filtrados do SQL Server, consulte a documentação.
Você pode usar a API Fluent para especificar um filtro em um índice, fornecido como uma expressão SQL:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.HasIndex(b => b.Url)
.HasFilter("[Url] IS NOT NULL");
}
Ao usar o provedor do SQL Server, o EF adiciona um 'IS NOT NULL' filtro para todas as colunas anuláveis que fazem parte de um índice exclusivo. Para substituir essa convenção, você pode fornecer um null valor.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.HasIndex(b => b.Url)
.IsUnique()
.HasFilter(null);
}
Colunas incluídas
Alguns bancos de dados relacionais permitem configurar um conjunto de colunas que são incluídas no índice, mas não fazem parte de sua "chave". Isso pode melhorar significativamente o desempenho da consulta quando todas as colunas da consulta são incluídas no índice como colunas chave ou não-chave, já que a tabela em si não precisa ser acessada. Para obter mais informações sobre as colunas incluídas do SQL Server, consulte a documentação.
No exemplo a seguir, a Url coluna faz parte da chave de índice, portanto, qualquer filtragem de consulta nessa coluna pode usar o índice. Mas, além disso, as consultas que acessam apenas as Title colunas e PublishedOn não precisarão acessar a tabela e serão executadas de forma mais eficiente:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Post>()
.HasIndex(p => p.Url)
.IncludeProperties(
p => new { p.Title, p.PublishedOn });
}
Verificar restrições
As restrições de verificação são um recurso relacional padrão que permite definir uma condição que deve ser mantida para todas as linhas de uma tabela; Qualquer tentativa de inserir ou modificar dados que violem a restrição falhará. As restrições de verificação são semelhantes às restrições não nulas (que proíbem nulas em uma coluna) ou às restrições exclusivas (que proíbem duplicatas), mas permitem que a expressão SQL arbitrária seja definida.
Você pode usar a API Fluent para especificar uma restrição de verificação em uma tabela, fornecida como uma expressão SQL:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<Product>()
.ToTable(b => b.HasCheckConstraint("CK_Prices", "[Price] > [DiscountedPrice]"));
}
Várias restrições de verificação podem ser definidas na mesma tabela, cada uma com seu próprio nome.
Nota: algumas restrições de verificação comuns podem ser configuradas através do pacote da comunidade EFCore.CheckConstraints.