2013-01-23 52 views
0

我有一個由字符串和數字概率組成的數據庫(還有其他列,但它們與問題無關)。一個簡化的模式是如何隨機化一個mysql列?

+-----------------------+----------------------+ 
| gopair    | P_high    | 
+-----------------------+----------------------+ 
| GO:0000398_GO:0030540 | 0.275997567007171 | 
| GO:0015198_GO:0016846 | 5.24489289777325e-06 | 
| GO:0034649_GO:0072141 | 0.00338367340340417 | 
| GO:0004303_GO:0031053 | 0.110417921058026 | 
+-----------------------+----------------------+ 

在我的工作中,我運行腳本查詢數據庫中與特定GO對關聯的值。我需要證明我的結果與隨機獲得的結果不同。所以,我想要運行的一個測試是洗牌P_high列,然後運行我的腳本並分析結果。

我試圖洗牌輸入文件並重新加載數據庫,但這很複雜,因爲輸入文件是一個7GB的文本文件,這是一種很難處理的機器上只有3GB內存。

那麼,有沒有辦法讓我的數據庫中的特定列隨機化,同時保持靜態?

注意事項:

  • 表中的問題是LARGE(60164966行)。
  • 我不需要嚴格的數學隨機性
  • 我需要保持相同的頻率。如果ñ對在真實的數據庫P的概率,我需要ň雙有在隨機一個P的概率。
  • 我需要解決方案是持久的。我的腳本可以多次查詢同一對數據庫,因此只需選擇一個隨機對就不夠好。
  • 我將需要重複所有這些操作,因此可以使用腳本(最好是Perl)解決方案。
  • 我在Ubuntu服務器上運行mysql版本14.14 Distrib 5.1.41,用於使用readline 6.1的debian-linux-gnu(x86_64)。
+0

'SELECT gopair,RAND()AS P_high FROM mytable'? –

+0

@SirRufo不起作用。我需要結果持久並反映原始數據庫的結構。所以,如果154個gopairs在原始數據庫中的概率爲0.005,那麼在隨機數據庫中,我需要154個gopairs以使概率爲0.005。如果我正確理解您的解決方案,那麼每次運行時都會從P_high列中選擇一個隨機值,對嗎? – terdon

+0

不,它只會返回一個隨機值*作爲P_high列。 Rufo案例中返回的值與數據庫中存在的值無關。 – Crontab

回答

1

此表的主鍵是什麼樣的?如果您使用整數代理鍵,您可以:[假設4字節整數]

  1. 轉儲所有鍵的列表。 $list[] [240MB給予或帶走]
  2. 複製列表。 $shuf[] [另一個240MB +/-]
  3. 隨機重複列表。 [隨機函數可能會返回一個副本,在這種情況下,跳過#2]
  4. 向表中添加另一列[即:shuffle_key],暫時沒有索引。
  5. 我不是非常熟悉Perl語法,但它類似於PHP這樣:

    $cnt = count($list); 
    for($i=0; $i<$cnt; $i++) { 
        $query = sprintf(
         'UPDATE table SET shuffle_key = %d WHERE primary_key = %d', 
         $shuf[$i], $list[$i]); 
        $dbh->doQuery($query); 
    } 
    
  6. 上創建新列的唯一索引。

  7. 現在,您可以在主鍵和混洗鍵上自行加入表格,並使用一側的gopair和另一側的P_high。

    SELECT t1.gopair, t2.P_high 
    FROM table t1 INNER JOIN table t2 
        ON t1.primary_key = t2.shuffle_key 
    

的內存這應該要求將大致2個主鍵的尺寸*的行數,但即使在較大的身邊,我沒有看到它佔用了超過一對夫婦的金額千兆字節。

注意:每次要混洗索引時,都需要在shuffle_index列上放置索引,以免在操作過程中出現重複鍵警告。之後重新添加索引。

+0

這看起來很有前途。不幸的是,主鍵是你在'gopair'列中看到的,但它們只是由列表元素形成的所有可能對的集合,所以我應該能夠很容易地生成它們。 ..我會玩你的想法和回報 – terdon

+1

@terdon每個'gopair'是12個字符,所以'60164966 * 12/1024/1024 = 688.5 MB'爲一個完整的列表,假設它們存儲爲單字節ASCII編碼。可用。 – Sammitch