客户端GUID生成没有表碎片成本

时间:2015-09-05 01:49:29

标签: c# sql-server entity-framework entity-framework-6

我想使用客户端生成GUID而没有它在数据库端的碎片成本(我不想考虑在数据库端生成主键,因为我想利用DDD和单元测试)。

我正在使用SQL Server 2012和Entity Framework 6。

  1. 为此,我在sql server中创建了一个表:
  2. 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))的聚簇索引。
    2. 所以,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. 另一种选择是使用选项1(没有其他聚集索引),但使用https://github.com/nhibernate/nhibernate-core/blob/master/src/NHibernate/Id/GuidCombGenerator.cs
      2. 中的ordercial GuidComb

        这将按某种顺序生成Guids:

        enter image description here

        问题:

        1. 选项1是否正确实施?
        2. 首选选项是什么:1,2,3或两者都没有?为什么?
        3. 选项3生成仅在最后一部分内排序的guid。这不会生成表碎片(如果使用id作为聚簇键)?
        4. 在选项2中,MyClusterKey列仅用于提供聚簇索引并避免表碎片?或者它可以有另一种用途?

1 个答案:

答案 0 :(得分:0)

我会选择选项2,因为你会理解它背后的逻辑,但是没有任何意义,因为无论如何都会有碎片。即便如此,性能下降也会相同甚至最差,因为应该在客户端进行更多的工作流程来组织它,就像在opt 2中一样,因为顺序逻辑不适用于场景中的页面。同样,我宁愿选择第二种选择,但它还取决于表格的消费或服务方式以及您尝试从中获取的内容。让我更深入地了解一下,如果你在threadlocal上共享一个上下文,顺序id应该是明确的方法,因为你可以控制创建的下一个键(因此opt3将是你的候选者),你将避免表碎片。但是,在某些情况下,最好不要控制EF中的线程安全性,让对象上下文处理它在任何情况下进入db的方式。对于这种情况,您将对数据库进行两次往返,因为只需要控制一个常规身份密钥来确认您获得的内容。但是如果你必须控制线程,那么选择3是要走的路,虽然你不会摆脱表碎片(至少从某些角度看其他来源)但你可以重用其他变量(在多个上下文wcf后面实现更高的吞吐量) 。在任何情况下,opt 2最适合于几种场景,这些场景将实现您希望在构建解决方案时实现的平衡。