【发布时间】:2014-05-12 22:55:10
【问题描述】:
我需要读取约 10.000 行的 excel 文件并将它们保存到 MySQL 中的表中。我使用的方法是创建一个foreach() 循环并在其中准备、绑定和执行每一行。
执行时间大约是 130 秒,我认为这很糟糕。那是在本地主机上,所以当脚本实时运行(共享主机)时,执行时间肯定会更长。
这是代码
ini_set('max_execution_time', 300);
$time_start = microtime(true);
$user = 'root';
$pass = '';
$driver_options = array(
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'",
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_OBJ,
);
try {
$dbh = new PDO('mysql:host=127.0.0.1;dbname=excel', $user, $pass, $driver_options);
} catch (PDOException $e) {
print "Error!: " . $e->getMessage() . "<br/>";
die();
}
set_include_path(get_include_path() . PATH_SEPARATOR . 'Classes/');
/** PHPExcel_IOFactory */
include 'PHPExcel/IOFactory.php';
$inputFileName = 'original.xls';
try {
$objPHPExcel = PHPExcel_IOFactory::load($inputFileName);
} catch(Exception $e) {
die('Error loading file "'.pathinfo($inputFileName,PATHINFO_BASENAME).'": '.$e->getMessage());
}
/*
cap [X] - loc [AK]
targa [D]
fabbrica [F]
provincia di residenza [V] - loc [AI]
comune di residenza [W] - loc [AJ]
data prima immatricolazione [AB]
dati anagrafici [T] - loc [AG]
*/
$xls = $objPHPExcel->getActiveSheet()->toArray(null,true,true,true);
$headers = $xls[1];
$loops = 0;
$rows = array_slice($xls, 1);
foreach ( $rows as $row ) {
$excelData = array(
'targa' => $row['D'],
'fabbrica' => $row['F'],
'immatricolazione' => $row['AB'],
'cap' => $row['AK'] == '' ? $row['X'] : $row['AK'],
'datiAnagrafici' => $row['AG'] == '' ? $row['T'] : $row['AG'],
'comuneResidenza' => $row['AJ'] == '' ? $row['W'] : $row['AJ'],
'provinciaResidenza' => $row['AI'] == '' ? $row['V'] : $row['AI']
);
$insert = $dbh->prepare("
INSERT INTO
data(targa, fabbrica, immatricolazione, cap, datiAnagrafici, comuneResidenza, provinciaResidenza)
VALUES(:targa, :fabbrica, :immatricolazione, :cap, :datiAnagrafici, :comuneResidenza, :provinciaResidenza)
");
$insert->execute($excelData);
if ( $insert->rowCount() != 1 ) {
echo 'Script interrupted at loop nr. '.$loops;
break;
}
++$loops;
}
$time_end = microtime(true);
$execution_time = ($time_end - $time_start);
echo '<b>Total Execution Time:</b> '.$execution_time.' s';
有什么方法可以优化代码性能吗?循环有问题吗?
谢谢。
【问题讨论】:
-
您可以先在循环外进行准备 - 查询的结构没有任何变化,是吗?
-
export excel to csv, LOAD DATA INFILE, 速度很快
-
查看自动提交并为此关闭它
-
@kingkero 太棒了。我将准备移到循环之外,执行时间下降到 8.40 秒
-
10,000 * 30+ 列 = 高 RAM 使用率。我对 PHPexcel 不是特别熟悉,但您可能想找到一种方法来逐行迭代它,而不是将整个文件加载到内存中。如果您的输入文件不断增长,您最终会耗尽可用内存。
标签: php mysql performance execution-time