优化MySQL查询(更新+子查询)

时间:2010-08-01 06:20:40

标签: sql mysql

我想更改 table_one 列的值,其中 = 1且 id 值为该行存在于 table_two 的列 other_id

中的任何位置

所以我正在使用此查询:

UPDATE table_one SET this='0' WHERE this='1' AND table_one.id IN (SELECT other_id FROM table_two);

查询花了几个小时没有完成,所以我想知道是否有办法更快地完成它。

如果重要的话, table_one.id table_two.other_id 都有唯一值。

table_one 有550k行

table_two 有30k行

MySQL 5.0.22

4 个答案:

答案 0 :(得分:1)

尝试使用EXISTS代替IN

答案 1 :(得分:1)

UPDATE...JOIN tuffkid Brian Hooper 提供的EXISTS答案的替代方案。我已经测试了两者,他们都花了相同的时间(我的电脑上2.52秒):

UPDATE table_one
JOIN table_two
  ON table_one.id = table_two.other_id
SET this=0
  WHERE table_one.this=1;

应该对已加入的列编制索引,如果table_two.other_id具有UNIQUE索引,则查询应该运行得非常快。

示例

创建表格:

CREATE TABLE `table_one` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `this` int(10) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  KEY `this` (`this`)
);

CREATE TABLE `table_two` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `other_id` int(10) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `other_id` (`other_id`)
);

插入一些测试数据:

DELIMITER //
DROP PROCEDURE IF EXISTS populate//
CREATE PROCEDURE populate()
BEGIN
    DECLARE i INT DEFAULT 0;
    WHILE i < 550000 DO
        INSERT INTO table_one (this) VALUES ((i MOD 18)+1);
        IF i MOD 18 = 0 THEN
            INSERT INTO table_two (other_id) VALUES (i+1);
        END IF;
        SET i = i + 1;
    END WHILE;
END;
//
DELIMITER ;

CALL populate();

运行更新:

UPDATE table_one
JOIN table_two
  ON table_one.id = table_two.other_id
SET this=0
  WHERE table_one.this=1;

Query OK, 30556 rows affected (2.52 sec)
Rows matched: 30556  Changed: 30556  Warnings: 0

UPDATE table_one
  SET this=0
  WHERE this=1 AND
    EXISTS (SELECT other_id
      FROM table_two
      WHERE other_id = table_one.id);

Query OK, 30556 rows affected (2.52 sec)
Rows matched: 30556  Changed: 30556  Warnings: 0

答案 2 :(得分:0)

扩展tuffkid的答案......

UPDATE table_one
    SET this='0'
    WHERE this='1' AND
          EXISTS (SELECT other_id
                      FROM table_two
                      WHERE other_id = table_one.id);

答案 3 :(得分:-1)

实际上解决方案是为table_one.id和table_two.other_id添加索引。 我提到它们是独一无二的,但我并不是说它们有索引,所以我不好澄清它。

添加索引后,查询花了不到一分钟。

同样用EXISTS替换IN会给我一个语法错误,所以我坚持使用IN。