0

假设您有一个随机数生成器吐出 1 到 100 000 000 之间的数字,并且您希望将它们存储在数据库 (MySQL) 中,并带有生成它们时的时间戳。如果出现了以前见过的数字,则将其丢弃。

实现这一目标的最佳算法是什么?根据需要选择然后插入?有什么更有效的吗?

4

4 回答 4

1

如果不需要每次都插入新的随机值,可以使用 INSERT IGNORE 或 REPLACE INTO。否则你应该选择检查然后插入。

于 2012-06-25T14:02:08.343 回答
1
  1. 你可以去SEQUENCE

    +

    • 没有关系被锁定,因此性能最佳;
    • 没有比赛条件;
    • 便携的。

    -

    • 在一系列数字中可能会出现“空白”。
  2. 你可以这样SELECT ...INSERT ...

    +

    • 没有差距,你也可以对你的数字做一些复杂的数学运算。

    -

    • 可以在 和 之间进行另一个并行会话,SELECTINSERT以 2 个相等的数字结束;
    • 如果存在UNIQUE约束,则先前的情况将导致异常;
    • 为避免这种情况,您可能会使用显式表锁,但这会立即对性能产生影响。
  3. 您可以选择INSERT ON DUPLICATE KEY UPDATE,到目前为止,它似乎是最好的选择(看看"INSERT IGNORE" 与 "INSERT ... ON DUPLICATE KEY UPDATE"),至少在我看来,唯一的例外 - 不能移植到其他 RDBMS。

PS这篇文章与 MySQL 无关,但值得一读以了解在您的过程中可能发生的所有问题。

于 2012-06-25T14:21:16.673 回答
0

这通常可以通过在表中的随机数列上创建唯一索引来解决。您可以尝试看看 b 树与散列是否具有更好的性能。

如果您有大量内存,您可以预先填充一个包含 100,000,000 行的表——所有可能的值。然后,当您查看是否已创建某些内容时,您只需要查看时间戳是否为非空。但是,这将需要超过 1 GB 的 RAM 才能将表存储在内存中,并且只有在您尝试最大化每秒事务数时才是最佳解决方案。

于 2012-06-25T14:14:54.857 回答
0

如果您UNIQUE在具有提取数字的列上放置索引,则任何复制键INSERT的尝试都将失败UNIQUE

因此,最简单和最便携的版本将是(PHP 代码,但你明白了):

function extraction() {
  do {
    $random = generate_random_number();
    $result = @mysql_query("INSERT INTO extractions(number) VALUE ($random)");
  } while (!$result);
  return $random;
}
于 2012-06-25T15:53:33.443 回答