我们有一个外部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。
答案 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快。)