维护数据库中的唯一值列表

时间:2012-06-25 13:58:50

标签: mysql performance

假设你有一个随机数生成器吐出1到100 000 000之间的数字,你想将它们存储在数据库(MySQL)中,并带有时间戳。如果先前看到的数字出现,则将其丢弃。

实现这一目标的最佳算法是什么? SELECT然后根据需要INSERT?有没有更高效的东西?

4 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

  1. 您可以选择SEQUENCE

    +

    • 没有关系被锁定,因此表现最佳;
    • 没有竞争条件;
    • 便携式的。

    -

    • 可能会在这一系列数字中获得“差距”。
  2. 您可以SELECT ...然后INSERT ...

    +

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

    -

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

  4. P.S。 This article与MySQL无关,但值得一读,以便了解可能发生的所有捕获。

答案 2 :(得分:0)

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

如果你有大量内存,你可以预先填充一个包含100,000,000行的表 - 所有可能的值。然后,当您查看是否已创建某些内容时,您只需要查看时间戳是否为非null。但是,这需要超过一千兆字节的RAM才能将表存储在内存中,如果您尝试每秒最大化事务处理,那么这只是最简单的解决方案。

答案 3 :(得分: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;
}