这article说:
与身份不同,列值的下一个数字将从内存中检索,而不是从磁盘中检索 - 这使得序列明显快于身份
这是否意味着身份证件来自磁盘?如果是,那么哪个磁盘和如何?
使用序列,我可以在日志中看到在插入新记录时对DB的额外选择查询。但在身份的情况下,我没有在日志中找到额外的选择查询。 那么序列如何变得比身份更快?
答案 0 :(得分:18)
序列使用的策略:
在插入新行之前,请向数据库询问下一个序列值,然后插入此行并返回序列值作为ID。
身份使用的策略:
插入行而不指定ID的值。插入行后,向数据库询问上次生成的ID。
因此在两种情况下查询的数量都相同。 但是,Hibernate默认使用一种对序列生成器更有效的策略。事实上,当它要求下一个序列值时,它会在内存中保留50(即dafault,IIRC和它的可配置)下一个值,并在接下来的50个插入中使用这50个下一个值。只有在插入50次之后,它才会进入数据库以获得50个下一个值。这极大地减少了自动ID生成所需的SQL查询数量。
身份策略不允许这样的优化。
答案 1 :(得分:13)
IDENTITY generator始终需要数据库命中来获取主键值,而不等待flush将当前entity state transitions与数据库同步。
因此IDENTITY生成器不能很好地与Hibernate write-behind第一级缓存策略配合使用,因此对于IDENTITY生成器禁用JDBC批处理。
序列生成器可以从数据库值预分配中受益,您甚至可以使用HI/LO optimization strategy。
在我看来,最好的生成器是pooled and pooled-lo sequence generators。这些生成器将批处理友好的序列生成器与客户端值生成优化相结合,该优化与其他可能插入行的数据库客户端兼容,而不了解我们的生成策略。
无论如何,你永远不应该选择TABLE生成器,因为it performs really bad。如果您需要可移植性,可以使用覆盖配置来解决它,如this article中所述。
答案 2 :(得分:0)
虽然我个人对Hibernate不熟悉,但据我所知,使用Identity基本上意味着Hibernate会检查数据库中下一个可能的id值是什么,并为它保留一个值。
对于序列,您基本上告诉Hibernate根据您提供的特定序列生成下一个值。因此,它必须通过查看下一个可能的id值来实际计算下一个id。因此,额外的查询被触发。
答案 3 :(得分:0)
也许这会回答你的问题:
与行所生成的标识列值不同 插入后,应用程序可以获取下一个序列号 通过调用NEXT VALUE FOR函数插入行。序列 即使数字,也会在调用NEXT VALUE FOR时分配编号 永远不会插入表中。 NEXT VALUE FOR功能可以 用作表定义中列的默认值。使用 sp_sequence_get_range获取一系列多个序列号 一次。
您可以找到详细信息here
身份不需要额外的选择查询,因为Identity是依赖于表的,而Sequence是独立于表的,但是因为这样我们甚至可以在创建行之前得到序列(当你执行session.save(T实体)时,序列是甚至在您提交事务之前生成)。
序列: 您创建或更新实体 - >每次保存实体 - > hibernate获取下一个序列值 - >您的程序在所有进程完成后返回值,无例外或回滚 - >你提交所有交易 - > hibernate插入所有完整的实体
identity:提交事务时,插入不完整的实体(必须从标识列中获取)。所以序列的 INSERT 命令肯定比较慢,但优点是如果取消插入,则计数不会增加。