最近我写了一个小程序,没什么值得注意的,主要是为了测试我发现的一些新东西,当时并不适合任何现实生活中的应用程序。其中一件事是使用UUID而不是我的Hibernate实体的序列生成(由底层Oracle数据库)ID。
我的一位同事认为这将是糟糕的设计,可能会对系统本身产生负面影响(ID不是由数据库传递,即失去控制)或性能(不产生UUID,但是数据库方面,处理它们)。是否有任何支持这一主张的观点或者是mumbo-jumbo?我的意思是,发生器是由Hibernate提供的,它不像某人一定认为它是一个好主意,也不是说摆脱序列似乎是一个很好的权衡,而不是它们是坏的,更多的是它们感觉像开销。 / p>
答案 0 :(得分:2)
如果您不喜欢序列(并且使用它们有缺点,例如跨实例的可移植性),那么为什么不使用Oracle的GUID?它还可用于自动生成主键:
create table my_tab2
(
val1 raw(16) default sys_guid(),
val2 varchar2(100),
primary key(val1)
)
table MY_TAB2 created.
> insert into my_tab2 (val2) values ('A test val')
1 rows inserted.
> commit
committed.
> select * from my_tab2
VAL1 VAL2
-------------------------------- ----------------------------------------------------------------------------------------------------
E8B47FA523673C97E040A8C014175791 A test val
您甚至不必关心如何填充PK(序列没有触发器或者在插入中不断使用seq.nextval)。看起来不是很漂亮(不像我想的那样“好看”)。
此外,如果您依赖于Hibernate(或数据库之外的任何其他应用程序/系统)来为表生成密钥,那么该表就会受到影响,100%依赖于Hibernate或任何外部系统来保持其持续的维护和完整性。数据属于公司,而不是应用程序。在我看来,数据库层应该尽可能独立(在这种情况下,简单地使用Oracle的sys_guid而不是Hibernate生成的东西会增加数据层的独立性)。在这种情况下看起来似乎微不足道,但为什么不使用Oracle首先提供的功能。
答案 1 :(得分:1)
完全不使用数据库生成主键可能是使用UUID的原因:您可以部署应用程序的多个实例并在本地生成ID,而无需全局协调器。 使用全局协调器会降低您的可伸缩性。
如果您进行批量插入,UUID可能会出现性能问题,因为它们均匀分布在密钥空间上,从而导致许多可能的尝试以确保密钥是唯一的。
根据您的数据库,您应该考虑根据UUID进行调整:Postgres有一个uuid列,在MySQL中您可能希望将其表示为二进制以避免UTF8开销。
UUID的另一个好处:如果您将ID公开给前端/最终用户,他就无法查看数据库中有多少个对象,也无法猜测下一个ID。
答案 2 :(得分:0)
UIID的大小是INTEGER(11)的许多倍,而这仅仅会对性能产生重大影响。我没有看到不使用已经内置到数据库的设施的任何原因。你必须证明这一过程是合理的,而不是你的同事。