【问题标题】:High CPU with mysql query when updating with inner join使用内部联接更新时使用 mysql 查询的高 CPU
【发布时间】:2017-11-24 09:23:47
【问题描述】:

我环顾四周并尝试了不同的方法,并希望改进我的大数据导入机制。在插入时导入数据效果很好,但是当我想根据 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 行,并且列可以更改。

希望示例代码清晰。

提前感谢您的帮助。

【问题讨论】:

  • key相同的情况下,为什么要用其中一个更新非key列,只保留第一个插入的记录,忽略其他的,也许也合适。
  • @Forward 因为两列中的键不一样。并且只能根据 ua 和 gm_id 要求进行更新。
  • @zuluk 我无法删除原始记录,因为它包含需要保留的值,这些值不存在于 temptable 中。因此,为什么只能更新某些列。
  • 有时在更新之前删除索引并在之后重新创建它会更有效。这取决于您的数据。
  • 也许您可以为 id-columns 采用更有效的数据类型:SELECT gm_id FROM table1 PROCEDURE ANALYSE();

标签: php mysql mariadb


【解决方案1】:

“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”

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

【讨论】:

  • 非常感谢您为我指明了正确的方向。我将进一步测试并阅读引用的文章。谢谢!
  • 非常感谢您的回答,我已经解决了我的问题。这就是我所做的。创建临时表时,我保留索引,而不是插入丢失的行并删除不再存在的行。比删除临时表上的 ua 和 gm_id 上的两个索引,而不是执行更新脚本。现在在不到 1 秒的时间内完成,并且没有 cpu 问题。
猜你喜欢
  • 2015-08-01
  • 2016-03-21
  • 2013-11-03
  • 1970-01-01
  • 2015-06-15
  • 2013-12-15
  • 2023-03-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多