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

mysql - how to insert multiple records and delete remaining ones

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

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 account*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])...

我怎样才能做得更好?

使用 not exists 从而单独保留现有记录并仅删除您未在列表中提供的记录..

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. INDEX(account) 添加到 X。

  2. 临时收集传入信息table。 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;

如果您正在使用 InnoDB,那么我推荐 BEGIN; DELETE...; INSERT...; COMMIT;。这将防止其他连接找到将要重新插入的已删除行。

如果那样太慢;我们再谈。

旁白:INT(32) -- "(32)" 没有任何意义。一个 INT 是一个 4 字节的整数,不管它后面的值是什么。