- 作者:zhaozj
- 发表时间:2020-12-23 10:59
- 来源:未知
来自: http://forum.javaeye.com/viewtopic.php?t=1071&postdays=0&postorder=asc&start=30
关于主键生成方式,主要有以下几种观点: 1、使用整数,键值在内存中; 2、使用整数,将键值保存到数据库中的一个表中; 3、使用UUID; 如果你对性能比较敏感,建议你不要使用UUID,一方面UUID的生成需要花一定的时间,另一方面,UUID的存储占用比整数更多的空间,对性能也很不利; 那么我们应该使用整数作为主键吗,答案是不确定的,要根据实际情况具体分析。 使用第一种方案,具有最高的效率,象Hibernate中的IncrementGenerator,由于hibernate本身就是跨数据库平台的,所以这种方式不用担心跨数据库平台的问题。但是第一种方案,不能应用在机群环境中。 第二种方式,能够应用机群环境中,向JBoss中的AutoNumber解决方案就是使用这种方式,但是这种方式也有很大的性能问题,当数据插入密集时,会导致冲突。 那么有没有一种高效率又能够应用在机群环境中的方案呢? 第一个方案具有最高的效率,但是不能应用在集群环境中,第二中方案能够应用在机群环境中,但是效率低。那么我们如果将这两种方案结合其来怎么样?那怎么结合呢? 我们来一起看一下这样的一个方案:我们知道对于第二种方案中,当要生成一个主键值时,系统会去读取并更新一次数据库中的表,相当于一次取值过程,每个主键值的生成都会有至少一次的数据库连接,而这正是性能瓶颈所在。为了解决这个问题,我们在每次“取值“时不是去出一个值,而是一次取出100个或更多,在每次需要生成主键值时,在内存中保存主键值的当前值和取值计数,当这个计数减小到0时,也就是前次取出的主键值已用完,这时再去数据库中取出100或更多的值。通过这种方式大大降低连接数据库的次数,减少冲突的可能性,可以大大提高第二中方案的性能问题,而且可以应用在机群环境中。 这种方案的取值部分,一般的都部署在一个EJB种,就像JBOSS中的AutoNumber,以进行事务隔离,防止主键更新事务与应用代码混在相同的事务中,当应用代码失败事务会滚时,将主键更新代码也回滚造成主键生成机制混乱。 当然这种方案也不是没有缺点,应该注意到,每次系统关闭时,都会造成一定的键值空当。大小与每次取值得个数有关。 在DudoJ框架中就实现了这种主键生成机制。DudoJ还实现了一个主键生成器,它是一个代理类,能够自动在第一种方案和最后一种方案间自动选择,已达到最好的性能。