【问题标题】:TRUNCATE and INSERT from temporary table versus INSERT into non-temp table and RENAMETRUNCATE 和 INSERT 从临时表与 INSERT 到非临时表和 RENAME
【发布时间】:2013-12-23 02:59:52
【问题描述】:

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

目前该脚本不做任何类型的差异,而是创建一个 SQL 脚本来创建一个临时表并将它生成的数据插入到该临时表中。然后它TRUNCATEs 生产表和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。

【问题讨论】:

    标签: mysql insert rename temp-tables truncate


    【解决方案1】:

    我使用的方法都不是:

    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),...
    

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

    如果要保留原始表,则首先创建它的副本,插入到副本中,然后将活动表重命名为备份,将新表重命名为活动表(与零停机模式更改的过程相同) .

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

    【讨论】:

    • 那将是理想的,是的,但有时会从表中删除行。我还不熟悉触发器,所以我必须研究它们。 PHP 脚本会根据其他表中的数据执行一些复杂的功能,所以我必须看看触发器是否能够做到这一点。
    • 有一个谷歌用于零停机时间架构更改 MySQL - 同样可以在这里应用。
    【解决方案2】:

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

    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;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-12-29
      • 1970-01-01
      • 1970-01-01
      • 2022-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多