Sdílet prostřednictvím


Indexy

Indexy jsou běžným konceptem v mnoha úložištích dat. I když se jejich implementace v úložišti dat může lišit, používají se k efektivnějšímu vyhledávání na základě sloupce (nebo sady sloupců). Další informace o dobrém využití indexů najdete v části Indexy v dokumentaci k výkonu.

Index ve sloupci můžete zadat následujícím způsobem:

[Index(nameof(Url))]
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}

Poznámka:

Podle konvence se index vytvoří v každé vlastnosti (nebo sadě vlastností), které se používají jako cizí klíč.

Složený index

Index může také zahrnovat více než jeden sloupec:

[Index(nameof(FirstName), nameof(LastName))]
public class Person
{
    public int PersonId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

Indexy ve více sloupcích, označovaných také jako složené indexy, urychlují dotazy, které filtrují sloupce indexu, ale také dotazy, které filtrují pouze první sloupce pokryté indexem. Další informace najdete v dokumentaci k výkonu.

Jedinečnost indexu

Ve výchozím nastavení nejsou indexy jedinečné: pro sadu sloupců indexu může mít více řádků stejné hodnoty. Index můžete nastavit jako jedinečný následujícím způsobem:

[Index(nameof(Url), IsUnique = true)]
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}

Pokus o vložení více než jedné entity se stejnými hodnotami pro sadu sloupců indexu způsobí vyvolání výjimky.

Pořadí řazení indexu

Poznámka:

Tato funkce se zavádí v EF Core 7.0.

Ve většině databází může být každý sloupec pokrytý indexem vzestupně nebo sestupně. U indexů, které pokrývají pouze jeden sloupec, to obvykle nezáleží: databáze může podle potřeby procházet index v obráceném pořadí. U složených indexů ale může být řazení pro dobrý výkon zásadní a může to znamenat rozdíl mezi indexem používaným dotazem nebo ne. Obecně platí, že pořadí řazení sloupců indexu by mělo odpovídat pořadím zadaným v ORDER BY klauzuli dotazu.

Pořadí řazení indexu je ve výchozím nastavení vzestupné. Všechny sloupce můžou mít sestupné pořadí:

[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; }
}

Pořadí řazení můžete zadat také podle sloupce takto:

[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; }
}

Pojmenování indexů a více indexů

Podle konvence jsou indexy vytvořené v relační databázi pojmenovány IX_<type name>_<property name>. U složených indexů <property name> se stane podtržítkem oddělený seznam názvů vlastností.

Název indexu vytvořeného v databázi můžete nastavit:

[Index(nameof(Url), Name = "Index_Url")]
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}

Všimněte si, že pokud zavoláte HasIndex více než jednou ve stejné sadě vlastností, bude stále konfigurovat jeden index, nikoli vytvořit nový:

modelBuilder.Entity<Blog>()
    .HasIndex(b => new { b.FirstName, b.LastName })
    .HasDatabaseName("IX_Names_Ascending");

modelBuilder.Entity<Blog>()
    .HasIndex(b => new { b.FirstName, b.LastName })
    .HasDatabaseName("IX_Names_Descending")
    .IsDescending();

Vzhledem k tomu, že druhé HasIndex volání přepíše první, vytvoří pouze jeden sestupný index. To může být užitečné pro další konfiguraci indexu vytvořeného konvencí.

Pokud chcete vytvořit více indexů ve stejné sadě vlastností, předejte název objektu HasIndex, který se použije k identifikaci indexu v modelu EF a k odlišení od ostatních indexů ve stejných vlastnostech:

modelBuilder.Entity<Blog>()
    .HasIndex(b => new { b.FirstName, b.LastName }, "IX_Names_Ascending");

modelBuilder.Entity<Blog>()
    .HasIndex(b => new { b.FirstName, b.LastName }, "IX_Names_Descending")
    .IsDescending();

Všimněte si, že tento název se také používá jako výchozí název databáze, takže explicitní volání HasDatabaseName není povinné.

Filtr indexu

Některé relační databáze umožňují zadat filtrovaný nebo částečný index. Díky tomu můžete indexovat pouze podmnožinu hodnot sloupce, což snižuje velikost indexu a zlepšuje výkon i využití místa na disku. Další informace o filtrovaných indexech SQL Serveru najdete v dokumentaci.

Rozhraní Fluent API můžete použít k určení filtru indexu, který se poskytuje jako výraz SQL:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasIndex(b => b.Url)
        .HasFilter("[Url] IS NOT NULL");
}

Při použití zprostředkovatele SQL Serveru EF přidá 'IS NOT NULL' filtr pro všechny sloupce s možnou hodnotou null, které jsou součástí jedinečného indexu. Pokud chcete tuto konvenci přepsat, můžete zadat null hodnotu.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasIndex(b => b.Url)
        .IsUnique()
        .HasFilter(null);
}

Zahrnuté sloupce

Některé relační databáze umožňují nakonfigurovat sadu sloupců, které se zahrnou do indexu, ale nejsou součástí jeho klíče. To může výrazně zlepšit výkon dotazů, pokud jsou všechny sloupce v dotazu zahrnuty do indexu jako klíčové nebo neklíčové sloupce, protože samotná tabulka nemusí být přístupná. Další informace o zahrnutých sloupcích SQL Serveru najdete v dokumentaci.

V následujícím příkladu Url je sloupec součástí indexového klíče, takže všechny filtrování dotazu na tento sloupec může index použít. Kromě toho dotazy, které přistupují jenom Title k tabulce a PublishedOn sloupcům, nebudou muset přistupovat k tabulce a budou fungovat efektivněji:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Post>()
        .HasIndex(p => p.Url)
        .IncludeProperties(
            p => new { p.Title, p.PublishedOn });
}

Kontrola omezení

Kontrola omezení jsou standardní relační funkce, která umožňuje definovat podmínku, která musí obsahovat všechny řádky v tabulce; jakýkoli pokus o vložení nebo úpravu dat, která porušují omezení, selže. Omezení kontroly jsou podobná omezením, která nemají hodnotu null (která zakazují hodnoty null ve sloupci) nebo jedinečná omezení (která zakazují duplicity), ale umožňují definovat libovolný výraz SQL.

Rozhraní Fluent API můžete použít k určení omezení kontroly v tabulce, které se poskytuje jako výraz SQL:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder
        .Entity<Product>()
        .ToTable(b => b.HasCheckConstraint("CK_Prices", "[Price] > [DiscountedPrice]"));
}

Ve stejné tabulce je možné definovat více omezení kontroly, z nichž každá má vlastní název.

Poznámka: Některá běžná omezení kontroly je možné nakonfigurovat prostřednictvím komunitního balíčku EFCore.CheckConstraints.