【问题标题】:Why is this MySQL query slowing down my code为什么这个 MySQL 查询会减慢我的代码速度
【发布时间】:2012-04-13 14:16:59
【问题描述】:

目前我有一个在 PHP 中运行的 MySQL 查询,在查看结果时我会更新原始表,但一个包含 500 行的简单表需要 30 秒才能完成:

$sqlquery = mysql_query('SELECT id, special_data FROM stats_visits WHERE processed = 0');
while($row = mysql_fetch_assoc($sqlquery)){ 
    $stat_id = $row['id'];
    // Make use of special_data field for some operations
    mysql_query('UPDATE stats_visits SET processed = 1 WHERE id = ' . $stat_id);
}

是因为我正在更新我从中选择的表吗?我已经通过执行以下操作解决了这个问题,但是由于该表将来可能有数千条记录,我不确定 IN 的支持情况如何:

$statids = array();

$sqlquery = mysql_query('SELECT id, special_data FROM stats_visits WHERE processed = 0');
while($row = mysql_fetch_assoc($sqlquery)){ 
    $statids[] = $row['id'];
    // Make use of special_data field for some operations
}

mysql_query('UPDATE stats_visits SET processed = 1 WHERE id IN(' . implode(',', $statids) . ')');

【问题讨论】:

  • 为什么要获取所有行并按 id 更新,而不是仅根据您在 SELECT 中使用的条件进行更新?
  • 在该选择中(我可能应该指出这一点)我选择更多数据,将其用于处理,一旦使用,我需要通过设置 processes=1 来表明这一点,因此在下一次运行中我可以跳过它.
  • 如果您所做的只是更新processed 列,那么没有理由运行SELECT 和UPDATE 查询。您可以使用下面提供的答案@Truth 来做到这一点。另一种选择是使用一组已编辑的数据并将所有内容组合成两个查询。
  • 您还可以研究使用临时表和交叉表更新 -> ricochen.wordpress.com/2011/06/21/…
  • 我不是简单地更新列,我已经编辑了我的问题,表明我选择了更多数据,使用它,然后一旦完成,我将该记录设置为“已处理”。

标签: php mysql query-optimization


【解决方案1】:

如果您只想将所有记录更新为processed = 1 为什么不使用单个查询来解决它?:

UPDATE `stats_visits` SET `processed` = 1 WHERE `processed` = 0;

【讨论】:

  • 因为在那个选择中(我可能应该指出这一点)我选择了更多数据,将其用于处理,一旦使用,我需要通过设置处理 = 1 来指示这一点,所以在下一次运行中我可以跳过它。
  • -1 如果他进行处理(如上所述),那么您可能会不小心将记录标记为已处理但实际上并未处理。
  • 在 OPs 查询中,他所做的一切都是选择行,然后更新这些行。有效地做@Truth 所说的事情是一回事。这是正确的答案。您的另一个选择是将UPDATE 与UPDATE 结合起来,用于“处理”“其他数据”..
  • 您还可以研究使用临时表和交叉表更新 -> ricochen.wordpress.com/2011/06/21/…
【解决方案2】:

在第一个版本中,每次更新都会访问一次数据库。这通常是个坏主意。第二个版本是访问数据库一次。

如果您担心这在未来会如何发挥作用,也许可以创建一个混合体。将更新分成 100 个组,并以块的形式更新它们。

【讨论】:

  • Batch 听起来是个好主意 - 实现它并且工作起来就像一个魅力,不用担心查询太长。谢谢。
【解决方案3】:

最简单的方法是将所有需要更新的 id 存储为一个数组,然后使用 IN 运算符将它们内爆到查询中。

例如

$processedArray= array();
while($row = mysql_fetch_assoc($sqlquery)){ 
    $stat_id = $row['id'];
    //Your processing goes here
    $processedArray[] = $stat_id; //Store an id if it needs updating as processed
}

mysql_query('UPDATE stats_visits SET processed = 1 WHERE id IN ('.implode(',', $processedArray).')');

【讨论】:

  • 这就是我最终所做的。
猜你喜欢
  • 2018-11-30
  • 1970-01-01
  • 2018-01-02
  • 1970-01-01
  • 2012-01-02
  • 2019-01-03
  • 1970-01-01
  • 2016-12-04
  • 2013-06-06
相关资源
最近更新 更多