数据库主键生成策略

     在建立数据库的时候,需要为每张表指定一个主键,所谓主键就是能够唯一标识表中某一行的属性或属性组,一个表只能有一个主键,但可以有多个候选索引。因为主键可以唯一标识某一行记录,所以可以确保执行数据更新、删除的时候不会出现张冠李戴的错误。数据库的主键生成有多种方式,每种方式都有其优点和缺点,应该根据不同的需求在主键的时间和空间效率上做平衡折中,从而选择不同的主键生成策略。归纳起来,对主键的选择主要有以下四种方式:
1.     自动增长字段
         自动增长型字段允许我们在向数据库添加数据时,不考虑主键的取值,记录插入后,数据库系统会自动为其分配一个值,确保绝对不会出现重复。
2.     手动增长字段
         手动增长型的字段,也就是说主键的值需要自己维护,通常情况下需要建立一张单独的表存储当前主键键值。
3.     GUID类型
         GUID是Globally Unique IDentifier的缩写,是一个128位的随机数,并保证不产生重复。
4.     COMB类型
         COMB(combine)型可以理解为一种改进的GUID,它通过组合GUID和系统时间,以使其在索引和检索事有更优的性能。  
下表列出四种主键生成方式优缺点的比较:
主键生成策略
优点
缺点
自动增长字段
1.  使用简单
1.        不同数据库获取当前值方式不同;
2.        难以应用在多个数据库间进行数据迁移的情况。
手动增长型字段
1.        可以获得最新键值
2.        可以确保数据合并过程中不会出现键值冲突
1.        通常情况下需要建立一张单独的表存储当前主键键值;
2.        增加一次数据库访问来获取当前主键键值;
3.        考虑并发冲突等,增加系统的复杂程度。
使用 GUID
1.        直接生成 GUID ,获得最新键值以填充主键,使用方便;
2.        可以确保数据合并过程中不会出现键值冲突;
3.        避免了前两种方式获取当前键值所增加的开销。
1.        占用较多存储空间;
2.        索引耗时;
3.        在多表链接查询时效率不如 int
使用 “COMB” 类型
1.        保留 GUID 的已有优点;
2.        利用时间信息与 GUID 组合起来,增加有序性以提高索引效率。
1.        需要设计 COMB 的生成算法;
2.        GUID 一样占用较多存储空间;
3.        在多表链接查询时效率不如 int 型,但优于 GUID

COMB类型主键生成实现:
COMB 数据类型的基本设计思路是这样的:既然 GUID 数据因毫无规律可言造成索引效率低下,影响了系统的性能,那么能不能通过组合的方式,保留 GUID 10 个字节,用另 6 个字节表示 GUID 生成的时间( DateTime ),这样我们将时间信息与 GUID 组合起来,在保留 GUID 的唯一性的同时增加了有序性,以此来提高索引效率。
NHibernate 中, COMB 型主键的生成代码如下所示:
/// <summary> 
/// Generate a new <see cref="Guid"/> using the comb algorithm. 
/// </summary>
     private Guid GenerateComb()
    {
       byte[ ] guidArray = Guid.NewGuid().ToByteArray();
    
      DateTime baseDate = new DateTime( 1900, 1, 1 );
      DateTime now = DateTime.Now;
        
       // Get the days and milliseconds which will be used to build    
       //the byte string    
      TimeSpan days = new TimeSpan( now.Ticks - baseDate.Ticks );
      TimeSpan msecs = now.TimeOfDay;
        
       // Convert to a byte array        
       // Note that SQL Server is accurate to 1/300th of a    
       // millisecond so we divide by 3.333333    
       byte[ ] daysArray = BitConverter.GetBytes( days.Days );
       byte[ ] msecsArray = BitConverter.GetBytes( ( long )    
        ( msecs.TotalMilliseconds/3.333333 ) );
        
       // Reverse the bytes to match SQL Servers ordering    
      Array.Reverse( daysArray );
      Array.Reverse( msecsArray );
        
       // Copy the bytes into the guid    
      Array.Copy( daysArray, daysArray.Length - 2, guidArray,    
        guidArray.Length - 6, 2 );
      Array.Copy( msecsArray, msecsArray.Length - 4, guidArray,    
        guidArray.Length - 4, 4 );
        
       return new Guid( guidArray );
    }

本文出自 “中尉” 博客,转载请与作者联系!

你可能感兴趣的:(数据,职场,主键,休闲)