如何提高使用MySQL的PHP​​脚本的速度?

时间:2014-08-04 14:00:24

标签: php mysql excel performance

我编写了一个PHP脚本,使用this library从excel文件中读取一些数据。

然后以任意顺序将它插入到MySQL数据库中的某些表中。

这个Excel文件有200行,有50列,通常执行时间超过60秒。因为我的PHP托管不允许我在你看来使用set_time_limit(0);如何提高我的脚本速度?

我的脚本读取每一行:

 function read_row($excelFile, $r){
    require_once './inc/excel_reader2.php';
    $data = new Spreadsheet_Excel_Reader($excelFile, FALSE);
    $col[0] = $data->val($r, 'E');
    $col[1] = $data->val($r, 'F');
    ...
    $col[49] = $data->val($r, 'BZ');
    return $col;
 }

我向MySQL插入数据的脚本:

$count = $user->rowcount($sheet=0); 
    if($final>0){
        $count = $final;
    }
    $users = 0;
    for($i = 4; $i <= $count; $i++){
        $f = $user->val($i,'D');
        $c = $user->val($i,'B');
        $l = $user->val($i,'C');
        $query = "INSERT INTO users(fullname ,ncode, location, createdtime) VALUES('$f','$c','$l', now());";
        if(mysql_query($query)){
            $users++;
        }
        $row = read_row($excelFile, $i);
        $query = "INSERT INTO `payments` (`id`, `year`, `month`, `user`, `p1`, `p2`,... `p50`) VALUES"
                . " (NULL, '$y', '$m', '$c', '$row[0]', '$row[1]', ..., '$row[49]');";
        mysql_query($query);
    } 

1 个答案:

答案 0 :(得分:2)

这里有一些事情:

使用microtime(true)对脚本进行基准测试。了解脚本的确切位置时间非常有用。

e.g。

$read_file_time = microtime(true); //true makes function return value in seconds
$data = new Spreadsheet_Excel_Reader($excelFile, FALSE);
$col[0] = $data->val($r, 'E');
$col[1] = $data->val($r, 'F');
...
$col[49] = $data->val($r, 'BZ');

//Output this to screen, or log it, or whatever    
$read_file_time = microtime(true) - $read_file_time; //end time - start time

return $col;

对数据库插入执行相同的操作。

接下来,我建议使用批量插入。

生成一个行数组并一次性插入所有行,而不是一次性使用您现在正在使用的单行。

所以你的数组看起来像

$rows = array(
  array('value for col-0', 'value for col-1' ... 'col-49'), //row 1
  array('value for col-0', 'value for col-1' ... 'col-49'), //row 2, etc.
);

您的查询看起来像

INSERT INTO `payments` (`id`, `year`, `month`, `user`, `p1`, `p2`,... `p50`) VALUES
(NULL, '$y', '$m', '$c', '$row[0][0]', '$row[0][1]', ..., '$row[0][49]'),
(NULL, '$y', '$m', '$c', '$row[1][0]', '$row[1][1]', ..., '$row[1][49]'),
...
(NULL, '$y', '$m', '$c', '$row[101][0]', '$row[101][1]', ..., '$row[101][49]')

根据文件的大小,您可能还需要批量执行此操作。

最后,你(正如@mellamokb指出的那样)你每个循环都打开文件。相反,你应该尝试类似的东西:

function read_row($ExcelFile, $r){

    /*$col[0] = $ExcelFile->val($r, 'E');
    $col[1] = $ExcelFile->val($r, 'F');*/

    //Instead of the above, use a loop
    $col = array();        
    $num_cols = $ExcelFile->colcount();        
    for($i = 0; $i < $num_cols; $i++) {
      $col[] = $ExcelFile->val($r, $i);
    }

    //Or you can use column names if you really want
    //Pass the `$col_names` as a function parameter tho
    $col_names = array('E', 'F', 'BZ');
    $num_cols = count($col_names);
    for($i = 0; $i < $num_cols; $i++) {
      $col[] = $ExcelFile->val($r, $col_names[$i]);
    }


    return $col;
 }

 require_once './inc/excel_reader2.php';
 $DataFile = new Spreadsheet_Excel_Reader('path to your file', FALSE);
 for($i = 4; $i <= $count; $i++) {
   $row = read_row($DataFile, $i);
 }

因此,要结合我的上述建议,您可以执行以下操作:

//@param $ExcelFile : excel reader2 file object
//@param $start_row : Row to start reading from, 0 based
//@param $num_rows  : Number of rows to read
function read_n_rows($ExcelFile, $start_row, $num_rows) {
   $rows = array();
   for($i = $start_row; $i < $num_rows; $i++) {
      $rows[] = read_row($ExcelFile, $i)
   }

   return $rows;
}