根据另一个表中的键更新大表

时间:2014-04-19 17:50:21

标签: mysql updates

我正在尝试更新一个表,并根据一个表(项)中的大量记录将查找ID设置为0,以确定第二个(backup_table)表中是否存在id(pk)。这两个表如下:

CREATE TABLE `items` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `lookupid` int(10) unsigned NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

CREATE TABLE `backup_table` (
  `item_id` int(10) unsigned NOT NULL,
  `backup_value` int(10) unsigned NOT NULL,
  PRIMARY KEY (`item_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

items表有大约600M行,backup_table有大约25M行。

我从这样的查询开始:

UPDATE items i
JOIN (SELECT i.id FROM items i
JOIN backup_table bu on i.id = bu.item_id
WHERE i.id != 0
LIMIT 10000) x ON i.id = x.id
SET i.id = 0;

我把它放在一个php包装器中,它将一直执行它直到它完成。每次迭代需要30-200秒,完成时间约为14.5小时。我需要大幅加快速度以适应我3小时的维护时间。任何有关加快这项工作的建议都会非常感激。

EXIST()会更好吗?这看起来怎么样?

1 个答案:

答案 0 :(得分:1)

首先,我很困惑。您已将items.id声明为主键,然后将其中10,000个设置为相同的值。这应该是一个错误。

假设您的查询与表定义之间存在一些不一致,您是否尝试过此版本?

UPDATE items i
    SET i.id = 0
    WHERE i.id <> 0 AND
          EXISTS (SELECT 1 FROM backup_table bu WHERE i.id = bu.item_id)
    LIMIT 10000;

这应该可以节省创建派生表的开销。

顺便说一下,使用limit而没有order by是可疑的,因为返回的行是以任意顺序。