2015-09-05 60 views
1

我想使用客戶端生成的GUID沒有它在數據庫端的碎片成本(我不想考慮生成數據庫端的主鍵,因爲我想利用DDD和單元測試)。客戶端的GUID生成沒有表碎片成本

我使用SQL Server 2012和Entity Framework 6

  1. 對於這一點,我創建了一個表中的SQL服務器:

enter image description here

與實體

public partial class Mac 
{ 
    public Mac() 
    { 
     this.Id = Guid.NewGuid() 
    } 
    public System.Guid Id { get; set; } 
    public string direccionMac { get; set; } 
} 
  1. 我明白這個設計會導致表碎片。因此,如下所示:https://stackoverflow.com/a/604842/310107我添加了另一列作爲名爲MyClusterKey(identity(1,1))的聚簇索引。

所以,Id,非集羣和主鍵。 MyClusterKey,聚簇索引,標識(1,1)

enter image description here

與實體:

public partial class Mac 
{ 
    public Mac() 
    { 
     this.Id = Guid.NewGuid(); 
    } 

    public System.Guid Id { get; set; } 
    public long MyClusterKey { get; set; } 
    public string direccionMac { get; set; } 
} 

MyClusteredKey加入作爲DatabaseGeneratedOption.Identity:

public class MacMap : EntityTypeConfiguration<Mac> 
    { 
     public MacMap() 
     { 
      // Primary Key 
      this.HasKey(t => t.Id); 

      // Properties 
      this.Property(t => t.MyClusterKey) 
       .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 

      this.Property(t => t.direccionMac) 
       .IsRequired() 
       .IsFixedLength() 
       .HasMaxLength(16); 

      // Table & Column Mappings 
      this.ToTable("Macs"); 
      this.Property(t => t.Id).HasColumnName("Id"); 
      this.Property(t => t.MyClusterKey).HasColumnName("MyClusterKey"); 
      this.Property(t => t.direccionMac).HasColumnName("direccionMac"); 
     } 
    } 
  • 另一種選擇是使用選項1(不含其他聚簇索引),但使用序列化升GuidComb在https://github.com/nhibernate/nhibernate-core/blob/master/src/NHibernate/Id/GuidCombGenerator.cs
  • 這會以某種順序生成的GUID:

    enter image description here

    問題:

    1. 是選項1正確實施?
    2. 什麼是首選選項:1,2,3都不是,爲什麼?
    3. 選項3正在生成僅在最後一部分內排序的guid。這不會生成表碎片(如果使用該ID作爲聚簇鍵)?
    4. 在選項2中,MyClusterKey列僅用於提供聚簇索引並避免表碎片?或者它可以有另一種用途?
    +0

    我的投票轉到選項2 – Biscuits

    +0

    也考慮'NEWSEQUENTIALID()' – Biscuits

    +0

    MyClusterKey是否在業務層中使用?這只是爲了防止碎片化,根本不會被使用? – nerlijma

    回答

    0

    我和選項3一樣,你會理解它背後的邏輯,但是沒有意義,因爲無論如何都會出現碎片。即使如此,性能下降將是相同的,甚至更糟,因爲在客戶端應該進行更多的工作流程來組織它,如opt 2所示,因爲序列邏輯不適用於場景中的頁面。再次,我寧願去第二選擇,但它也取決於如何消費或服務表,以及你試圖從中獲得什麼。讓我更深入地探討一下,如果你在threadlocal上共享一個上下文,順序標識應該是權威的方法,因爲你可以控制下一個創建的鍵(因此opt3將成爲你的候選),你將避免表碎片。但是,在某些情況下,最好不要控制EF中的線程安全性,並讓對象上下文在任何情況下都處理到數據庫的方式。對於那種情況,你將會對db進行兩次往返,就像控制一個普通的身份密鑰一樣,以確認你得到的是什麼。但是如果你必須控制線程,opt 3是要走的路,儘管你不會擺脫表碎片(至少從某些角度來看是來自其他來源),但是你可以重用其他變量(以獲得更高的吞吐量,在多個上下文wcf後面) 。無論如何,opt 2最適合於多種場景,以滿足您在構建解決方案時想要達到的平衡效果。

    +0

    MyClusterKey是否在業務層中使用?這只是爲了防止碎片化,根本不會被使用? – nerlijma

    +1

    只要你不使用MyClusterKey(甚至沒有出現在代碼中)表碎片不應該發生,你會安全的 – diegogravisaco