我可以通过JPA或数据库级别为数据库表主键设置MAX值吗?如果不可能,那我就是在考虑
key
(9999999999是我的MAX)key
对数据库执行SELECT,如果返回对象为null
,则INSERT,如果不重复则返回步骤1 所以如果我做了上述两个问题。请记住,环境是高并发的:
Q1:使用SELECT进行检查的开销是否存在,INSERT是否显着?我的意思是:这个过程是否正常,因为通常我让DB为我创建一个独特的PK?
Q2:如果Q1没有造成显着的性能下降,我可以遇到并发问题吗?例如,如果带有Id1的P1检查表,则Id1不存在,它准备插入,P2潜入插入Id1之前P1可以。因此,当P1插入Id1时,它会失败。我不希望这个过程在这里失败,我希望它回到循环中,找到一个新的id,重复这个过程。我该怎么做?
我的环境是SQL和MYSQL db。我将JPA与Eclipselink实现一起使用
注意:有些人质疑我以这种方式实施它的决定,答案正是下面TravisJ
建议的答案。我有一个非常高的并发环境。当一个进程启动时,我需要为另一个进程创建一个请求,向该进程传递一个唯一的10个字符长的id。由于环境是高电流,我想利用PK的独特而非空特征。请求中包含大量信息,因此我创建了一个Request
表,请求ID为我的PK。我知道因为所有的DB索引他们的PK,查询PK很快。如果有更好的方法,请告诉我。
答案 0 :(得分:2)
您可以在表定义中实现Check Constraint:
CREATE TABLE P
(
P_Id int PRIMARY KEY NOT NULL,
...
CONSTRAINT chk_P_Id CHECK (P_Id>0 and P_Id<9999999999)
)
编辑:如评论中所述,MySql不遵守CHECK约束。这是bug日志中存在的6年缺陷,MySql团队还没有修复它。由于MySql现在由Oracle Corp监管,它可能永远不会被修复(仅仅被视为“文档限制”,不喜欢它的人可以升级到付费DBMS)。但是,此语法和检查约束功能本身可用于Oracle,MS SQL Server(包括SQLExpress / MSDE),MS Access,Postgre和SQLite。
答案 1 :(得分:2)
为什么不从1开始并使用自动增量?这将更加高效,因为您不会遇到冲突,您必须循环。如果你的数字用完了,你将会在同一条船上,但至少按顺序进行,你不必处理碰撞。
想象一下,当你用完了90%的可用数字时,试图找到一个未使用的密钥。这将花费一些时间,并且如果你随机生成它,它总是有可能(在你的生命中)找不到未使用的密钥。
此外,使用自动增量,很容易判断您是否接近极限(SELECT MAX(col)
)。您可以编写警报脚本,以便在需要重置时通知您。对于随机方法,该查询会是什么样的?
如果您使用的是InnoDB,那么您仍然可能不想使用主键。将随机记录插入聚簇索引是一种性能损失,因为必须重新排序实际的表数据。而是使用唯一键(使用自动增量主键)。
在相关列上使用唯一索引,只需在该范围内生成一个随机数并尝试插入。如果插入失败,则生成新号码并重试。如果插入成功,则继续。这解决了并发问题。
然而,顺序自动增量键将产生更好的性能。
答案 2 :(得分:1)
请参阅,
http://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing
和,
http://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing#Advanced_Sequencing
JPA已经拥有良好的Id生成支持,实现自己的生成没有意义。
如果您关注并发性和性能,并使用MySQL,我建议使用具有大预分配大小的TABLE生成器(在其他数据库上我建议使用SEQUENCE生成器)。如果您有大量数据,请确保使用long来表示您的身份。
如果你真的认为你需要更多,那么考虑UUID id生成。 EclipseLink 2.4提供了一个@UUIDGenerator。