【问题标题】:Efficently prune MySQL duplicate records (PHP)高效修剪 MySQL 重复记录 (PHP)
【发布时间】:2012-01-08 20:33:27
【问题描述】:

我想修剪 MySQL 数据库中的所有重复条目,只留下最早或最新的一个,具体取决于 $keep 是什么。我正在使用以下内容,但速度很慢:

function pruneDuplicates($keep) {

  if($keep == 1)
    $order = "ASC";
  else if ($keep == 0)
    $order = "DESC";

  //Go through and find the duplicate hashes.  Grab the IDs that correspond to them then delete all but one ID

  $query = "SELECT HEX(hash) FROM hashes GROUP BY hash HAVING count(hash) > 1";

  $result = mysql_query($query) or die("ERROR: ".mysql_error());
  while ($row = mysql_fetch_array($result)) {
      $query = "SELECT id from hashes WHERE hash = UNHEX('$row[0]') ORDER BY id $order LIMIT 1";
      $innerResult = mysql_query($query) or die("ERROR: ".mysql_error());
      $innerRow = mysql_fetch_array($innerResult);
      $query = "DELETE FROM hashes WHERE hash = UNHEX('$row[0]') AND id != $innerRow[0]";
      echo $query."<br>";
      mysql_query($query) or die("ERROR: ".mysql_error());

  }

  echo "Prune successful...";

}

echo $query 用于调试。该脚本需要几分钟才能运行。它修剪了大约 80,000 条记录(我有超过 100,000 条记录,但预计会有 1,000,000 条以上)。我在看 mysqladmin proc stat,发现删除需要时间。

我的表说明如下:

+-----------+------------+------+-----+-------------------+----------------+
| Field     | Type       | Null | Key | Default           | Extra          |
+-----------+------------+------+-----+-------------------+----------------+
| id        | int(11)    | NO   | PRI | NULL              | auto_increment |
| date      | timestamp  | NO   |     | CURRENT_TIMESTAMP |                |
| hash      | binary(16) | NO   | MUL | NULL              |                |

哈希是一个索引。

【问题讨论】:

  • 我怀疑您可以使用单个 DELETE 查询,其中显示 DELETE everything with hash = 'hashtodelete' AND id != 'onetokeep'。请注意,这是伪代码。循环这样做会很慢。
  • 这基本上就是我正在做的事情,但是我必须找到要删除的散列,因此上面的 select 语句。查找重复的哈希...对于每个哈希获取第一个或最后一个 ID->DELETE WHERE id != id 和 hash = hashtodelete...重复
  • 啊,我明白了。好吧,如果您从第一个获得 hashid 值,我认为您可以消除第二个 SELECT。您可以为IN() 构建一个字符串,然后将id 与您不想删除的ids 放在NOT (IN ...) 中。

标签: php mysql optimization


【解决方案1】:

无论您如何调整以加快速度,删除这样的许多行都会很慢。不要一次删除所有行,而是尝试通过在查询中包含LIMIT 子句来批量执行它们。此外,请确保从 cron 作业而不是从您网站上的链接运行脚本,如果您想真正安全,请增加或禁用 PHP 执行时间限制,这样您就不会在删除阶段遇到它.

【讨论】:

    猜你喜欢
    • 2011-12-20
    • 1970-01-01
    • 2012-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-26
    相关资源
    最近更新 更多