使用内部联接更新时使用mysql查询的高CPU

时间:2017-11-24 09:23:48

标签: php mysql mariadb

我已经四处寻找并尝试了不同的方法,并希望改进我的大数据导入机制。在insert上导入数据效果很好,但是当我想根据2 where语句更新现有数据时遇到了问题。

我首先从源加载数据并将其放在CSV文件中,而不是使用LOAD DATA LOCAL INFILE来导入临时表中的数据。

从临时表到主表的插入方式,按预期工作。快速并使用少量的服务器资源。



INSERT INTO $table ($fields) SELECT $fields FROM $temptable WHERE (ua,gm_id) NOT IN (SELECT ua,gm_id FROM $table)




我没有以下更新记录,我创建此方法的原因是因为重复键上的更新不起作用。因为它总是插入一个新的记录。我想我不明白这种方法是如何工作的,或者没有以正确的方式使用它。 UA和GM_ID都是两个表上的索引,但无法使其工作。下面脚本的问题是,如果我更新8000行,它使用200%的CPU并需要5到8分钟。这当然不是很好。



$query = "UPDATE $table a INNER JOIN $temptable b ON a.gm_id=b.gm_id AND a.ua=b.ua SET ";
    foreach($update_columns as $column => $status){
      $query .= "a.$column=b.$column,";
    }
    $query = trim($query, ",");
    $result = $pdo->query($query);




有人能指出我应该使用的正确方向。

我想将临时表中的某些列更新到主表。此代码在白天执行分配。有时可以只更新100行,但有时可以更新8k或60k行,并且列可以更改。

我希望样本代码清晰。

提前感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

“UA和GM_ID都是两个表上的索引” - 两个单独的索引是错误的方法。您必须具有“复合”UNIQUE(UA, GM_ID)(按任意顺序)。如果该对不是唯一的,那么您就不能使用IODKU。

WHERE .. NOT IN ( SELECT ... )效率非常低。 WHERE ... NOT EXISTS ( SELECT ... )更好; LEFT JOIN ... WHERE .. IS NULL甚至更好。请参阅http://mysql.rjweb.org/doc.php/staging_table#normalization

中的“SQL#1”

阅读该博客的其余部分,了解有关高速摄取的更多提示。