我如何随机化一个mysql列?

时间:2013-01-23 17:24:31

标签: mysql random

我有一个由字符串和数字概率组成的数据库(还有其他列,但它们与问题无关)。简化的架构是

+-----------------------+----------------------+
| 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 RAM的机器上很难处理。

那么,有没有一种方法可以随机化我的数据库中的特定列,同时保持其余的静态?

注意事项:

  • 有问题的表格很大(60,164,966行)。
  • 我不需要严格的数学随机性
  • 我需要保持相同的频率。如果 N 对在真实数据库中具有 P 的概率,我需要 N 对具有 P 在随机的一个。
  • 我需要解决方案是持久的。我的脚本可以多次查询数据库中的同一对,所以简单地选择一个随机对就不够了。
  • 我需要反复进行所有这些操作,因此首选可编写脚本(最好是Perl)的解决方案。
  • 我在Ubuntu服务器上使用readline 6.1运行mysql Ver 14.14 Distrib 5.1.41,对于debian-linux-gnu(x86_64)。

1 个答案:

答案 0 :(得分:1)

此表的主键是什么样的?如果您使用整数代理键,您可以:[假设4字节整数]

  1. 转储所有密钥的列表。 $list[] [240MB give-or take]
  2. 复制列表。 $shuf[] [另一个240MB +/-]
  3. 随机播放重复列表。 [shuffle函数可能会返回一个副本,在这种情况下会跳过#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. 在新列上创建一个UNIQUE索引。

  7. 现在,您可以在主键和随机密钥上自行加入表格,并从一侧使用gopair,从另一侧使用P_high。

    SELECT t1.gopair, t2.P_high
    FROM table t1 INNER JOIN table t2
      ON t1.primary_key = t2.shuffle_key
    
  8. 这应该需要的内存量大约是主键*行数的2倍,但即使在较大的一侧,我也看不到占用的内存超过几千兆字节。

    注意:每次要重新排列索引时,都需要删除shuffle_index列上的索引,这样就不会在操作过程中出现重复的键警告。之后重新添加索引。