PHP一般原则:是一个很好的SQL调用或许多小的调用

时间:2014-05-21 16:10:05

标签: php mysql optimization lamp

这是一个优化问题RE:第一原则..想象一下,我正在做一个重大的提升比较.. 30k文件vs 30k数据库条目..是一个最大的进程效率做一个大的MySQL进入一个数组然后循环物理文件检查与数组相比,或者最好循环访问文件,然后一次一行MySQL调用..

这里有一些伪代码可以帮助解释:

 //is this faster?
 foreach($recursiveFileList as $fullpath){
     $Record = $db->queryrow("SELECT * FROM files WHERE fullpath='".$fullpath."'");
     //do some $Record logic           
 }


 //or is this faster
 $BigList = array();
 $db->query("SELECT * FROM files");
 while($Record = $db->rows()){
     $BigList[$Record['fullpath']] = $Record;
 }

 foreach($recursiveFileList as $fullpath){
     if (isset($BigList[$fullpath])){
         $Record = $BigList[$fullpath];
         //do some $Record logic
     }   
 }

1 个答案:

答案 0 :(得分:1)

  

更新:如果您总是知道您的$ recursiveFileList是表的100%,那么每行执行一次查询将是不必要的开销。在这种情况下,只需使用SELECT * FROM files

我不会使用你展示的两种风格中的任何一种。

第一种样式为每个单独的完整路径运行一个单独的SQL查询。这会导致SQL解析,优化等的一些开销。请记住,MySQL不具备从一次类似查询的调用到下一次调用的记忆查询优化的能力。它每次分析并执行查询优化。开销相对较小,但却相加。

第二种样式显示从表中获取所有行,并在应用程序层中对其进行排序。这有一个很多的开销,因为通常您的$recursiveFileList可能只匹配表中的1%或0.1%或更小部分的行。我已经看到通过网络传输过多数据的情况实际上耗尽了1Gbps网络交换机,这为应用程序的每秒请求设置了上限。

明智地使用查询条件和索引让RDBMS检查并仅返回匹配的行。

您展示的两种风格并非唯一选项。我建议使用范围查询来匹配单个查询中的多个文件fullpath值。

$sql = "SELECT * FROM files WHERE fullpath IN (" 
    . array_fill(0, count($recursiveFileList), "?") . ")";
$stmt = $pdo->prepare($sql);
$stmt->execute($recursiveFileList);
while ($row = $stmt->fetch()) {
    //do some $Record logic           
}

注意我还使用带有?参数占位符的预准备查询,然后在调用execute()时单独传递完整路径值数组。 PDO对此很好,因为您可以只传递一个数组,并且数组元素与参数占位符匹配。

在这种情况下,这也解决了SQL注入的风险。