我可以为数据库表主键添加MAX值吗?

时间:2012-04-04 20:55:26

标签: java mysql sql jpa eclipselink

我可以通过JPA或数据库级别为数据库表主键设置MAX值吗?如果不可能,那我就是在考虑

  1. 在0-9999999999之间创建一个随机key(9999999999是我的MAX)
  2. 使用新创建的key对数据库执行SELECT,如果返回对象为null,则INSERT,如果不重复则返回步骤1
  3. 所以如果我做了上述两个问题。请记住,环境是高并发的:

    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很快。如果有更好的方法,请告诉我。

3 个答案:

答案 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。