Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/368.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 利用数据库表生成唯一随机数_Java_Oracle - Fatal编程技术网

Java 利用数据库表生成唯一随机数

Java 利用数据库表生成唯一随机数,java,oracle,Java,Oracle,我们有一个每周生成1000万个随机数的过程,并将它们存储在Oracle数据库表中。 我们有以下逻辑来创建给定范围的随机数。我们保持生成数与先前生成数的严格唯一性 已经在db表中。我们通过索引存储随机数的表列并在插入到表中时捕获异常来实现这一点 在异常情况下重新生成随机数。完成这一过程几乎需要1天的时间,并继续增加所需的处理时间 请帮助我们解决以下问题,以提高此过程的性能 有没有可能改进我们的随机数生成算法? 是否有可能改进数据库操作 我们尝试过的事情: 我们已经尽可能多地清除了表数据。 “向表中

我们有一个每周生成1000万个随机数的过程,并将它们存储在Oracle数据库表中。 我们有以下逻辑来创建给定范围的随机数。我们保持生成数与先前生成数的严格唯一性 已经在db表中。我们通过索引存储随机数的表列并在插入到表中时捕获异常来实现这一点 在异常情况下重新生成随机数。完成这一过程几乎需要1天的时间,并继续增加所需的处理时间

请帮助我们解决以下问题,以提高此过程的性能

有没有可能改进我们的随机数生成算法? 是否有可能改进数据库操作 我们尝试过的事情: 我们已经尽可能多地清除了表数据。 “向表中批量插入2500条记录”将过程增加到3-4天,因为每个异常都会导致重新创建每批编号。 我们正在评估并行处理以获得一些改进

int itemsInPack = 10000000;
int pinLength = 10;
int randomSeedByteCount = 10;
long lowerRangeValue = (long) Math.pow(10.0, (double) (pinLength - 1));
long higherRangeValue = 10 * lowerRangeValue;
long numberRange = higherRangeValue - lowerRangeValue;

SecureRandom secureRandomNumberGen = SecureRandom.getInstance("SHA1PRNG");
byte[] bytes = new byte[1024 / 8];
secureRandomNumberGen.nextBytes(bytes);
byte[] seed = secureRandomNumberGen.generateSeed(randomSeedByteCount);
secureRandomNumberGen.setSeed(seed);

for(int k=0;k<itemsInPack;k++){
    double nextDouble = secureRandomNumberGen.nextDouble(); 
    long fraction = (long)(numberRange * nextDouble);
    long pinNumber = (long)(fraction + lowerRangeValue);//Insert this to table
    System.out.println("pinNumber: " + pinNumber);
}

您可以尝试使用Oracle的功能在数据库中完成这一切:

Oracle安装程序:

插入:

这是在100-140秒内插入1000000行

您可以删除循环并将代码简化为:

INSERT INTO randomValues
SELECT rnd
FROM   (
  SELECT DISTINCT
         FLOOR(
           DBMS_RANDOM.VALUE(
             POWER( 10, 10 ),
             POWER( 10, 11 )
           )
         ) AS rnd
  FROM   DUAL
  CONNECT BY ROWNUM <= :numRows * 1.1
) r
WHERE ROWNUM <= :numRows
AND   NOT EXISTS ( SELECT 'X'
                   FROM   randomValues e
                   WHERE  e.rnd = r.rnd );

但是,我所做的测试数量很少,插入1000000行大约需要200秒。

您不能使用Oracle中的存储过程来完成吗?这似乎是最合适的方法?这些随机数的用例是什么?在数据库中,生成一个从最小值到最大值的数字列表-随机排序,然后得到前n行。我只会在客户实际需要时生成一个随机数,例如38位长,将其存储在具有唯一约束的表中。如果随机数足够长,任何客户获得违反唯一约束错误的可能性都很低,您可以忽略它。您可能每周都会在低活动期间清除表中的过期PIN。下面的文章介绍了一种在少量固定时间内生成大量安全唯一ID的方法。存储空间很小。查询也是一个微小的常量时间。如果你仍然在寻找一个优化的解决方案,你应该看看:非常感谢你的建议。我们将尝试这些方法,并让您知道结果。对于响应延迟,我们深表歉意,因为我们目前受到洪水的影响,并且对互联网的访问仍然有限。我们已通过执行以下更改,将处理时间缩短到约4小时。通过ThreadLocalRandom.current.nextLonglowerRangeValue、higherRangeValue和引入并行处理生成随机数。抱歉,我们没有尝试建议的DBMS_RANDOM.VALUE低,高
DECLARE
  batchSize NUMBER(4,0) := 2500;
  numRows   NUMBER(8,0) := 1000000;
BEGIN
  FOR i IN 1 .. numRows LOOP
    INSERT INTO randomValues
    SELECT rnd
    FROM   (
      SELECT DISTINCT
             FLOOR(
               DBMS_RANDOM.VALUE(
                 POWER( 10, 10 ),
                 POWER( 10, 11 )
               )
             ) AS rnd
      FROM   DUAL
      CONNECT BY ROWNUM <= batchSize * 1.1
    ) r
    WHERE ROWNUM <= batchSize
    AND   NOT EXISTS ( SELECT 'X'
                       FROM   randomValues e
                       WHERE  e.rnd = r.rnd );
  END LOOP;
END;
/
INSERT INTO randomValues
SELECT rnd
FROM   (
  SELECT DISTINCT
         FLOOR(
           DBMS_RANDOM.VALUE(
             POWER( 10, 10 ),
             POWER( 10, 11 )
           )
         ) AS rnd
  FROM   DUAL
  CONNECT BY ROWNUM <= :numRows * 1.1
) r
WHERE ROWNUM <= :numRows
AND   NOT EXISTS ( SELECT 'X'
                   FROM   randomValues e
                   WHERE  e.rnd = r.rnd );