mysql - 如何插入多个记录并删除剩余的记录

时间:2015-03-03 21:02:30

标签: mysql query-optimization database-performance

让我们从一个例子开始。有桌子:

CREATE TABLE  X (
 id INT(32) NOT NULL auto_increment,
 account INT(32),
 value INT(32),
 primary KEY (id)
)

我想要实现的是确保给定帐户具有指定的值集(并且只有这些值)。基本上,如何有效地在下面做:

delete from X where account = 5;
insert into X (account, value) values 
(5, 0), 
(5, 2), 
(5, 3)
...
(5, 99);

需要注意的是,通常只有一个值会发生变化(出现或消失)。 几乎我有一组值会发生变化,但是我不需要接收增量,而是需要有效地反映差异。给定帐户的价值不会超过100个,通常只有2-3个。这些变化每秒发生数千次。对同一帐户的更改很少见(通常只有几个,但偶尔会更多)。

我想到的是设置id帐户* 1000 + sequence_id以增加具有相同帐户的行的数据位置。而且我可以做(伪代码)而不是删除+重新插入:

$current_values = select value from X where account = 5;
$to_add = $new_values not in $current_values
$to_remove = $current_values not in $new_values
delete from X where value in $to_remove
insert into X (account, value) values (5, $to_add[0]), (5, $to_add[1])...

我怎样才能做得更好?

2 个答案:

答案 0 :(得分:0)

使用不存在因此单独保留现有记录,并删除您未在列表中提供的那些记录。

Delete from X t1 where not exists
(Select 1 from X t2 where t1.account=t2.account and t1.value=t2.value
and value in (0,2,3,...99))

现在如果你有办法识别0,2,3 ... 999而不必传入它,那就更好了,因为你可能会使用in子句遇到限制。

这一切都包含在一个声明中,使其不易受多个用户使用同一帐户的问题的影响。

答案 1 :(得分:0)

  1. INDEX(account)添加到X。

  2. 将传入的信息收集到临时表中。 tmp

  3. DELETE X FROM X, ( SELECT DISTINCT account FROM tmp ) y WHERE x.account=y.account; [检查语法,并在投入生产前进行测试。]

  4. INSERT INTO X (account, value) SELECT (account, value) FROM tmp;

  5. 如果您使用InnoDB,我建议BEGIN; DELETE...; INSERT...; COMMIT;。这将使其他连接无法找到即将重新插入的行。

    如果那太慢了;让我们进一步讨论。

    抛开:INT(32) - “(32)”意味着什么。 INT是一个4字节的整数,无论​​其后面的值如何。