我应该使用Oracle的sys_guid()生成guid吗?

5
我有一些继承的代码,每次创建实体时都会调用 SELECT SYS_GUID() FROM DUAL。这意味着每次插入数据都会有两个对 Oracle 的调用,一个是获取 Guid,另一个是插入数据。
我想可能有一个很好的原因,例如 - Oracle 的 Guid 可能经过优化,以便通过连续进行索引树的重新平衡来实现高容量插入。
使用 SYS_GUID 而不是在客户端上构建自己的 Guid 有什么理由吗?

1
我能换一种方式表达吗?当有本地实现时,您应该避免构建自己的GUID。但这并不一定是使用sys_guid()的理由。它比使用序列慢得多,并且是原始数据类型,比简单数字更麻烦。如果这只在一个数据库中,为什么不能为所有内容使用单个序列呢? - Ben
我应该明确指出,我所知道的所有客户端使用的语言都有 GUID 类型。因此,在 C# 中创建一个新的 Guid 是通过 Guid.NewGuid(),而在 Java 中相同的操作是通过 UUID.randomUUID() 来实现的。当我说“构建自己的”时,我的意思并不是编写大量代码,而是创建一个新的 Guid。由于 Guids 被保证是唯一的,它们在哪里创建应该没有任何区别。这个问题只涉及到在 Oracle 中创建你的 Guid 相对于客户端创建的相对优势。我知道在插入时在 Oracle 中创建 guid 的方法是(程序上昂贵的)。 - cmdematos
4个回答

7
为什么要自己造轮子,如果你已经有提供的呢?此外,您不需要先获取再插入,您只需直接插入即可:
create table my_tab
(
val1 raw(16),
val2 varchar2(100)
);

insert into my_tab(val1, val2) values (sys_guid(), 'Some data');
commit;

您还可以将其用作主键的默认值:

drop table my_tab;
create table my_tab
(
val1 raw(16) default sys_guid(),
val2 varchar2(100),
primary key(val1)
);

这里不需要设置before insert trigger来使用序列(在大多数情况下,甚至不需要关心val1或代码中的其它内容如何生成)。

另外,序列也需要更多的维护。更不用说在不同系统之间移动数据时的可移植性问题了。

但是,在我看来,序列更加易于人类理解(使用数字比使用原始值的32位十六进制版本要好得多)。可能还有其他序列的优点,我没有进行过广泛的比较,你可以先运行一些性能测试。


谢谢。我理解序列相对于Guid的优势之一是主键,特别是聚集主键受益于顺序数据(不一定是整数/数字顺序类型),因为算法被优化以避免B树重新平衡。显然很难/不可能使用随机数据(如我们的GUID)做到同样的效果。但是,sys_guid()看起来非常顺序,尽管序列位于guid的“中间”。因此有这个问题。 - cmdematos

4

如果你担心会有两个数据库调用,你可以在INSERT语句中调用SYS_GUID()。你甚至可以使用RETURNING子句来获取Oracle生成的值,以便在应用程序中进一步使用。


谢谢,这两个调用是我关注的问题之一。我知道我可以在插入时生成Guid,但这在程序上是昂贵的。 - cmdematos
我想知道是否存在可靠的理由选择在服务器上创建所有Guid主键,而不是在客户端上创建。 - cmdematos
只要自欺欺人到了一定程度,任何事情都可以被辩解;)。我会说你随时可以生成GUID而不会有人说你做错了。老实说,在某些情况下,在客户端创建GUID是有意义的。如果您正在进行批量加载或需要在多个表或数据集之间保持GUID一致性。也许还有,如果您在不同的数据库之间工作,您可能不想在每个系统中独立创建GUID。但是,我不知道您所说的“程序上昂贵”是什么意思。 - Adam Hawkes

3

SYS_GUID可以用作主键列的默认值,这通常比使用序列更方便,但请注意该值将是更或多或少随机的,而不是连续的。好处是可能会减少热块的争用,但缺点是索引插入也会分散。我们通常不建议使用此方法。

参考点击这里


1
我发现没有理由从Oracle生成Guid。每个Guid在Oracle和客户端之间的往返可能比偶尔出现的随机值插入时发生的索引重新平衡要慢。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接