PHP 循环 - SQL 性能不佳

PHP loop - poor SQL performance

我正在遍历 40 个关联数组:

array(
  'key0' => value,
  'url0' => value,
  'tit0' => value,
  'cdn0' => value,
  'cdn1' => value,
  'cdn2' => value,
)

我正在执行多个 select 和一个 可能 insert 查询。我试图通过减少查询量来优化性能。

foreach($buf){
  $sth1->execute();//SELECT * FROM metadata WHERE url = '{$buf['url0']}'
  $sth2->execute();//SELECT * FROM metadata WHERE key = '{$buf['key0']}'

  if(!$ret=$sth1->fetch(PDO::FETCH_ASSOC)){
    if($sth2->fetch(PDO::FETCH_ASSOC)){
      die( 'key duplicate - error' );
    }

    $data[ ] = $buf;

    $sth3->execute();//INSERT INTO metadata ...
  } else {
    $data[ ] = $ret; 
}

但是这很慢(循环大约需要 4.2 秒)。我尝试通过删除查询使其更快。

foreach($buf){
  $sth1->execute();//SELECT * FROM metadata WHERE url = '{$buf['url0']}' OR key = '{$buf['key0']}'

  if(!$ret=$sth1->fetch(PDO::FETCH_ASSOC)){       
    $sth3->execute();//INSERT INTO metadata ...

    $data[ ] = $buf;
  } else {
    if($ret['key']==$generated_key){die('key duplicate - error');}

    $data[ ] = $ret; 
}

由于某种原因,这使它变得更慢(5-6 秒)。因此,我一无所知。我怎样才能让它有一个合理的加载时间?我尝试将 $sth2->execute 放在 if(!$ret...) 语句中,但这也没有给我任何速度增益。

似乎 INSERT 不是问题所在,因为大多数 array 数据已经 IN 数据库。每当我 运行 在 phpmyAdmin 中查询时,它都会在 0.0000000003 秒内完成,所以它一定与循环有关。

你认为有这种可能吗? https://dev.mysql.com/doc/refman/5.0/en/insert-select.html

很遗憾,关于您的 MySQL 索引策略或您 select 的信息量不足。

第一秒想到的可能问题:

  • 当您从 MySQL 执行查询时,您命中了查询缓存,来自循环缓存的内容在某个时候已过期
  • 数据库中糟糕的索引策略 - selection by varchar 并不总是最好的解决方案,使用 char(16) 和 MD5 sum(或类似的东西)可能是更好的方法
  • 你在迭代中有一些未被注意到的循环

所有这些的解决方案是回显大量带有精确时间戳的调试数据,阅读它们并将 SQL 查询记录到 MySQL 服务器日志和 运行 所有这些console/PHPMyAdmin 一批,以便更好地调试。

加速 #1:将 $sth2->execute(); 移动到第一个 if 之后。如果 url 测试成功,您似乎不需要结果。

加速 #2:确保有 INDEX(url)INDEX(key)

加速 #3:将 INDEX(key) 更改为 UNIQUE(key) 并跳过 SELECT ... key;在执行 INSERT.

后只需检查 dup 密钥

加速 #4:(这个可能有帮助也可能没有帮助。)在单个查询中完成所有 SELECT ... urlSELECT ... url IN (40-urls-in-list)。 (需要 Speedup #2。)将结果保存在一个关联数组中并遍历它以完成其余的 SELECT/INSERT 事情。

加速 #5:构建一个 'batch' INSERT 单个 INSERT 中的多行),然后 execute它在 40 项循环的末尾。

请提供SHOW CREATE TABLE.

MyISAM?还是InnoDB?您是否已将 innodb_buffer_pool_size 调整为大约可用 RAM 的 70%?如果不是,这可能会提高性能。