2016-05-17 74 views
1

我們有一個每週生成1000萬個隨機數的過程,並將它們存儲在數據庫表(Oracle)中。 我們有下面的邏輯來創建給定範圍的隨機數字。我們保持生成號碼的嚴格唯一性與先前生成的號碼 (已在db表中)。在插入表 (異常情況下重新生成隨機數)時,我們通過索引存儲隨機數和捕獲異常的表列來實現此目的。完成這一過程需要將近一天的時間,並繼續增加所需的處理時間。用數據庫表生成唯一隨機數

請幫助我們進行以下查詢以改善此過程的性能。

  1. 任何可能的方法來改善我們的隨機數生成算法?
  2. 任何可能性,以提高數據庫的操作

的事情,我們嘗試: 我們已經清除多達可以表數據。 對錶格的批插入(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); 
} 
+0

您不能在Oracle中使用存儲過程來執行此操作嗎?這似乎是最合適的方法? – RobAu

+0

還有什麼是隨機數的用例? – RobAu

+0

在數據庫中,生成一個從最小值到最大值的數字列表 - 隨機排序,然後獲取前n行。 – MT0

回答

2

您可以嘗試使用Oracle的DBMS_RANDOM.VALUE(low, high)功能做這一切在數據庫:

甲骨文設置

CREATE TABLE randomValues (
    rnd NUMBER(11,0) PRIMARY KEY 
); 

插入

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; 
/

這將在100 - 140秒之間插入1,000,000行。

您可以刪除循環和代碼簡化爲:

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); 

然而,測試的少數我已經做了,這是服用約200秒插入1,000,000行。

+0

非常感謝您的建議。我們將嘗試這些,並讓您知道結果(對不起,因爲我們現在受到洪水的影響而延遲迴應,並且仍然限制訪問互聯網) –

+0

通過進行以下更改,我們設法將處理時間縮短到約4小時。 通過ThreadLocalRandom.current()。nextLong(lowerRangeValue,higherRangeValue)生成隨機數並引入並行處理。 (對不起,我們還沒有試過建議的DBMS_RANDOM.VALUE(低,高)) –