TRUNCATE和INSERT从临时表与INSERT到非临时表和RENAME

时间:2013-12-05 22:47:22

标签: mysql insert rename temp-tables truncate

我们有一个外部PHP脚本,它从数据库中的各个表中提取数据,以便为同一数据库中的其他几个表创建更新。出于这个问题的目的,我不会深入了解该脚本的内容或它如何生成数据,但我感兴趣的是它如何更新数据库中的表。

目前,该脚本不执行任何类型的diff,而是创建一个SQL脚本,该脚本创建临时表并将其生成的数据插入到该临时表中。然后TRUNCATE生成表和INSERT / SELECT临时表中的所有内容。 我应该注意,此脚本生成的数据在每次运行时都可能不同,基于在其他表中删除,添加或更改的内容。

以下是它正在做的消毒版:

CREATE TEMPORARY TABLE tbl0_temp (col1, col2, col3, PRIMARY KEY  (col1,col), UNIQUE KEY tuple (user_id,nas_id));

INSERT INTO tbl0_temp VALUES (valA1, valB1, valC1),(valA2, valB2, valC2),(valA3, valB3, valC3),...you get the idea.

TRUNCATE TABLE tbl0_prod;

INSERT INTO tbl0_prod SELECT * FROM tabl1_temp;

这种方法在几年前生产表(tbl0_prod)中只有几千行的情况下运行良好,但现在我们接近几百万。鉴于此,该方法并不是非常慢,但在某些副本上,INSERT / SELECT最多可能需要30秒。这是远程机器上的应用程序没有获得所需数据的30秒,人们注意到了。

我希望有更好,更快,影响更小的方式来更新该表。我想知道创建/更新“真实”表并简单地进行一些重命名是否有效。以下是我在想的一个例子:

CREATE TABLE IF NOT EXISTS tbl0_temp LIKE tbl0;

TRUNCATE TABLE tbl0_temp;

INSERT INTO tbl0_temp VALUES (valA1, valB1, valC1),(valA2, valB2, valC2),(valA3, valB3, valC3),...

RENAME TABLE tbl0 TO tbl0_old, tbl0_temp to tbl0;

RENAME TABLE tbl0_old TO tbl0_temp;

保留tbl0_tmp表背后的想法是,如果出现问题,将内容重命名很容易,但我可以放弃tblo_old,甚至不必担心截断在开始。 在我的脑海中,这似乎是一个好主意,但这是我在后端可能产生影响的知识差距的地方。有没有人碰巧(我提供的信息有限)有关这是否会起作用,或者是一个坏主意?

主要副本和大多数副本上的版本是5.0.46。所有相关表格都是MyISAM。

2 个答案:

答案 0 :(得分:1)

仅供参考...对于我需要做的事情,我描述的方法非常有效。

CREATE TABLE IF NOT EXISTS tbl0_temp LIKE tbl0;

TRUNCATE TABLE tbl0_temp;

INSERT INTO tbl0_temp VALUES (valA1, valB1, valC1),(valA2, valB2, valC2),(valA3, valB3, valC3),...

RENAME TABLE tbl0 TO tbl0_old, tbl0_temp to tbl0;

RENAME TABLE tbl0_old TO tbl0_temp;

答案 1 :(得分:0)

我使用的方法既不是:

INSERT IGNORE INTO tbl0 
VALUES 
(valA1, valB1, valC1),
(valA2, valB2, valC2),
(valA3, valB3, valC3),...

或者

REPLACE INTO tbl0 
VALUES 
(valA1, valB1, valC1),
(valA2, valB2, valC2),
(valA3, valB3, valC3),...

或者,如果由于某种原因我想要一些非常复杂的规则,我会使用触发器。

如果要保留oriinal表,请先创建它的副本,插入副本,然后将实时表重命名为备份,将新表重命名为live(与零停机时间模式更改相同的过程)

(您考虑过改为Innodb - 它有更好的并发支持,在某些情况下运行速度比MyISAM快。)