23

这篇文章说:

与 identity 不同,列值的下一个数字将从内存而不是磁盘中检索——这使得 Sequence 比 Identity 快得多

这是否意味着ID来自磁盘以防身份?如果是,那么哪个磁盘以及如何

使用序列,我可以在日志中看到插入新记录时对 DB 的额外选择查询。但是在身份的情况下,我没有在日志中找到额外的选择查询。那么序列如何变得比身份更快

4

4 回答 4

43

序列使用的策略:

在插入新行之前,向数据库询问下一个序列值,然后以返回的序列值作为 ID 插入这一行。

身份使用的策略:

在不指定 ID 值的情况下插入一行。插入行后,向数据库询问最后生成的 ID。

因此,在这两种情况下,查询的数量是相同的。但是,Hibernate 默认使用对序列生成器更有效的策略。事实上,当它请求下一个序列值时,它会在内存中保留 50 个(即默认值,IIRC,它是可配置的)下一个值,并将这 50 个下一个值用于接下来的 50 次插入。只有在 50 次插入后,它才会进入数据库以获取 50 个下一个值。这极大地减少了自动 ID 生成所需的 SQL 查询数量。

身份策略不允许这样的优化。

于 2013-07-22T10:34:44.980 回答
27

生成器IDENTITY将始终需要数据库命中来获取主键值,而无需等待刷新以将当前实体状态转换与数据库同步。

因此IDENTITY生成器不能很好地与 Hibernate 后写一级缓存策略配合使用,因此IDENTITY生成器禁用了 JDBC 批处理。

序列生成器可以从数据库值预分配中受益,您甚至可以采用hi/lo优化策略。

在我看来,最好的生成器是pooledpooled-lo序列生成器。这些生成器将批处理友好的序列生成器与客户端值生成优化相结合,该优化与其他可能在不了解我们生成策略的情况下插入行的 DB 客户端兼容。

无论如何,您永远不应该选择TABLE生成器,因为它的性能非常糟糕。

于 2014-12-13T17:25:43.350 回答
0

也许这会回答你的问题:

与插入行时生成的标识列值不同,应用程序可以在插入行之前通过调用 NEXT VALUE FOR 函数获取下一个序列号。在调用 NEXT VALUE FOR 时分配序列号,即使该编号从未插入到表中。NEXT VALUE FOR 函数可用作表定义中列的默认值。使用 sp_sequence_get_range 一次获取多个序列号的范围。

你可以在这里找到详细信息

Identity 不需要额外的选择查询,因为 Identity 依赖于表,而 Sequence 独立于表,但正因为如此,我们甚至可以在创建行之前获取序列(当你执行 session.save(T entity) 时,序列甚至在之前生成你提交交易)。

序列:您创建或更新实体->每次保存实体时->休眠获取下一个序列值->您的程序在所有进程完成后返回值,无异常或回滚->您提交所有事务->休眠插入所有完整实体

身份:提交事务时,插入不完整的实体(必须从身份列中获取)。所以序列的INSERT命令肯定更慢,但优点是如果取消插入,计数不会增加。

于 2013-07-22T06:26:56.490 回答
0

虽然我个人是 Hibernate 的新手,但据我回忆,使用 Identity 基本上意味着 Hibernate 将检查您的数据库中下一个可能的 id 值是什么,并为它保留一个值。

对于序列,您基本上告诉 Hibernate 根据您提供的特定序列生成下一个值。所以它必须通过查看下一个可能的 id 值来实际计算下一个 id。因此,触发了额外的查询。

于 2013-07-22T05:25:43.757 回答