索引數

索引是許多資料存放區中常見的概念。 雖然其在資料存放區中的實作可能會有所不同,但用來根據資料行(或資料行集)進行查閱會更有效率。 如需良好索引使用方式的詳細資訊,請參閱效能檔中的索引一節

您可以透過資料行指定索引,如下所示:

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

注意

根據慣例,索引會建立在做為外鍵的每個屬性 (或屬性集) 中。

複合索引

索引也可以跨越多個資料行:

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

多個資料行的索引,也稱為 複合索引 ,可加速查詢,以篩選索引的資料行,但也加速查詢,這些查詢只會篩選 索引所涵蓋的第一個 資料行。 如需詳細資訊, 請參閱效能檔。

索引唯一性

根據預設,索引不是唯一的:允許多個資料列具有索引資料行集的相同值。 您可以讓索引成為唯一的,如下所示:

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

嘗試插入多個具有相同值之索引資料行集的實體,將會導致擲回例外狀況。

索引排序次序

注意

這項功能正在 EF Core 7.0 中引進。

在大部分的資料庫中,索引所涵蓋的每個資料行都可以是遞增或遞減。 若索引只涵蓋一個資料行,這通常並不重要:資料庫可以視需要以相反順序周遊索引。 不過,對於複合式索引而言,排序對於良好的效能至關重要,而且可能表示查詢所使用的索引之間的差異。 一般而言,索引資料行的排序次序應該對應至查詢子 ORDER BY 句中指定的排序次序。

索引排序次序預設為遞增。 您可以讓所有資料行都有遞減順序,如下所示:

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

您也可以依資料行指定排序次序,如下所示:

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

索引命名和多個索引

依照慣例,在關係資料庫中建立的索引會命名為 IX_<type name>_<property name> 。 針對複合索引, <property name> 會變成以底線分隔的屬性名稱清單。

您可以設定資料庫中建立的索引名稱:

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

請注意,如果您在相同屬性集上呼叫 HasIndex 一次以上,該屬性會繼續設定單一索引,而不是建立新的索引:

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();

由於第二 HasIndex 個呼叫會覆寫第一個呼叫,因此只會建立單一遞減索引。 這對於進一步設定慣例所建立的索引很有用。

若要在同一組屬性上建立多個索引,請將名稱傳遞至 HasIndex ,該名稱將用來識別 EF 模型中的索引,並將它與其他索引區隔開相同的屬性:

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();

請注意,此名稱也會作為資料庫名稱的預設值,因此不需要明確呼叫 HasDatabaseName

索引篩選

某些關係資料庫可讓您指定篩選或部分索引。 這可讓您只編制資料行值的子集索引,減少索引的大小,並改善效能和磁碟空間使用量。 如需 SQL Server 篩選索引的詳細資訊, 請參閱檔

您可以使用 Fluent API 來指定索引的篩選,並提供為 SQL 運算式:

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

使用 SQL Server 提供者 EF 時,會針對屬於唯一 'IS NOT NULL' 索引的所有可為 Null 資料行新增篩選。 若要覆寫此慣例,您可以提供 null 值。

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

包含的資料行

某些關係資料庫可讓您設定一組包含在索引中的資料行,但不是其「索引鍵」的一部分。 當查詢中的所有資料行都包含在索引中做為索引鍵或非索引鍵資料行時,這可能會大幅改善查詢效能,因為不需要存取資料表本身。 如需 SQL Server 內含資料行的詳細資訊, 請參閱檔

在下列範例中,資料 Url 行是索引鍵的一部分,因此該資料行的任何查詢篩選都可以使用索引。 但此外,只存取 和 PublishedOn 資料行的 Title 查詢不需要存取資料表,而且會更有效率地執行:

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

檢查條件約束

檢查條件約束是標準關聯式功能,可讓您定義必須保存資料表中所有資料列的條件;任何嘗試插入或修改違反條件約束的資料都會失敗。 檢查條件約束類似于非 Null 條件約束(禁止資料行中的 Null)或唯一條件約束(禁止重複專案),但允許定義任意 SQL 運算式。

您可以使用 Fluent API 來指定資料表上的檢查條件約束,並提供為 SQL 運算式:

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

您可以在相同的資料表上定義多個檢查條件約束,每個資料表都有自己的名稱。

注意:您可以透過社群套件 EFCore.CheckConstraints 來設定一些常見的檢查條件約束。