php 如何提高数据库中 csv 数据的插入速度?
How to improve the speed of insertion of the csv data in a database in php?
我写的这段代码允许读取一个文件夹,根据文件名插入不同的tablecsv文件的数据。一旦文件被处理,它就会被移动到另一个文件夹。
我的代码运行良好,但第二个 csv 文件超过 80 000 行,需要几个小时才能集成到我的数据库中。
如何提高代码的性能?我尝试了 'LOAD DATA LOCAL' 但没有成功...
<?php
include("../connexion.php");
ini_set('max_execution_time', 54000);
$timestamp= date("y-m-d H:i");
$dir = 'D:/xampp/htdocs/retail_BI/test/';
$allFiles = scandir($dir);
$dest = 'D:/xampp/htdocs/retail_BI/test/files/';
foreach($allFiles as $file) {
if (!in_array($file,array(".","..")))
{
$file = $dir.$file;
$filename = basename( $file );
if ( strpos( $filename, 'BI1_' ) === 0 ) {
if (($handle = fopen("$filename", "r")) !== false) {
//To remove BOM in the fist cell
fseek($handle, 3);
while (($data = fgetcsv($handle, 9000000, ";")) !== false) {
if (empty(array_filter($data))) {
echo "not good";
continue;
}
$date = DateTime::createFromFormat('d/m/Y H:i:s A', $data[2]);
if ($date === false) {
break;
}
$date1 = $date->format('Y-m-d'); // 2020-07-07
$date2 = $date->format('Hi A'); // 1247 AM
//database entry
$query = "insert into dbo.Y2_Sales (storenumber, storename, date, time, TransRef, stylecode, color, size, quantity, unit_price, SalesExGST, cost, currency)
values('$data[0]', '$data[1]','$date1','$date2','$data[3]','$data[4]','$data[5]','$data[6]','$data[7]', '$data[8]','$data[9]','$data[10]','$data[11]')";
$stmt = $conn->query( $query );
if (!$stmt) { echo $conn->error;}
}
}
fclose($handle);
//Moving the file to another folder
if(!rename($file, $dest . $filename)) {
echo "error copy";
}
} else if ( strpos( $filename, 'BI2_' ) === 0 ) {
if (($handle = fopen("$filename", "r")) !== false) {
//To remove BOM in the fist cell
fseek($handle, 3);
while (($data = fgetcsv($handle, 9000000, ";")) !== false) {
// print_r($data);
if (empty(array_filter($data))) {
continue;
}
//database entry
$query = "insert into dbo.Y2_Inventory (storenumber, stylecode, colour, size, units, timestamp)
values('$data[0]', '$data[1]','$data[2]','$data[3]','$data[4]', '$timestamp')";
$stmt = $conn->query( $query );
if (!$stmt) { echo $conn->error;}
// $query = "LOAD DATA LOCAL INFILE '$filename' INTO TABLE dbo.Y2_Inventory FIELDS TERMINATED BY ';' LINES TERMINATED BY '\n' (storenumber, stylecode, colour, size, units, timestamp)";
// $stmt = $conn->query( $query );
}
}
fclose($handle);
//Moving the file to another folder
if(!rename($file, $dest . $filename)) {
echo "error copy";
}
}
}
}
echo "good !";
?>
尝试批量插入,而不是将每一行的数据插入数据库。
您始终可以执行批量插入,这可以获取 n(使用 1000)个条目并将其插入 table。
https://www.mysqltutorial.org/mysql-insert-multiple-rows/
这将减少数据库调用,从而减少总时间。
对于 80k 的条目,您也有可能超出内存限制。
您可以使用 php 中的生成器来克服这个问题。
https://medium.com/@aashish.gaba097/database-seeding-with-large-files-in-laravel-be5b2aceaa0b
虽然,这是在Laravel,但是从csv中读取的代码是独立的(使用生成器的代码),逻辑可以在这里使用。
我写的这段代码允许读取一个文件夹,根据文件名插入不同的tablecsv文件的数据。一旦文件被处理,它就会被移动到另一个文件夹。 我的代码运行良好,但第二个 csv 文件超过 80 000 行,需要几个小时才能集成到我的数据库中。
如何提高代码的性能?我尝试了 'LOAD DATA LOCAL' 但没有成功...
<?php
include("../connexion.php");
ini_set('max_execution_time', 54000);
$timestamp= date("y-m-d H:i");
$dir = 'D:/xampp/htdocs/retail_BI/test/';
$allFiles = scandir($dir);
$dest = 'D:/xampp/htdocs/retail_BI/test/files/';
foreach($allFiles as $file) {
if (!in_array($file,array(".","..")))
{
$file = $dir.$file;
$filename = basename( $file );
if ( strpos( $filename, 'BI1_' ) === 0 ) {
if (($handle = fopen("$filename", "r")) !== false) {
//To remove BOM in the fist cell
fseek($handle, 3);
while (($data = fgetcsv($handle, 9000000, ";")) !== false) {
if (empty(array_filter($data))) {
echo "not good";
continue;
}
$date = DateTime::createFromFormat('d/m/Y H:i:s A', $data[2]);
if ($date === false) {
break;
}
$date1 = $date->format('Y-m-d'); // 2020-07-07
$date2 = $date->format('Hi A'); // 1247 AM
//database entry
$query = "insert into dbo.Y2_Sales (storenumber, storename, date, time, TransRef, stylecode, color, size, quantity, unit_price, SalesExGST, cost, currency)
values('$data[0]', '$data[1]','$date1','$date2','$data[3]','$data[4]','$data[5]','$data[6]','$data[7]', '$data[8]','$data[9]','$data[10]','$data[11]')";
$stmt = $conn->query( $query );
if (!$stmt) { echo $conn->error;}
}
}
fclose($handle);
//Moving the file to another folder
if(!rename($file, $dest . $filename)) {
echo "error copy";
}
} else if ( strpos( $filename, 'BI2_' ) === 0 ) {
if (($handle = fopen("$filename", "r")) !== false) {
//To remove BOM in the fist cell
fseek($handle, 3);
while (($data = fgetcsv($handle, 9000000, ";")) !== false) {
// print_r($data);
if (empty(array_filter($data))) {
continue;
}
//database entry
$query = "insert into dbo.Y2_Inventory (storenumber, stylecode, colour, size, units, timestamp)
values('$data[0]', '$data[1]','$data[2]','$data[3]','$data[4]', '$timestamp')";
$stmt = $conn->query( $query );
if (!$stmt) { echo $conn->error;}
// $query = "LOAD DATA LOCAL INFILE '$filename' INTO TABLE dbo.Y2_Inventory FIELDS TERMINATED BY ';' LINES TERMINATED BY '\n' (storenumber, stylecode, colour, size, units, timestamp)";
// $stmt = $conn->query( $query );
}
}
fclose($handle);
//Moving the file to another folder
if(!rename($file, $dest . $filename)) {
echo "error copy";
}
}
}
}
echo "good !";
?>
尝试批量插入,而不是将每一行的数据插入数据库。
您始终可以执行批量插入,这可以获取 n(使用 1000)个条目并将其插入 table。
https://www.mysqltutorial.org/mysql-insert-multiple-rows/
这将减少数据库调用,从而减少总时间。
对于 80k 的条目,您也有可能超出内存限制。
您可以使用 php 中的生成器来克服这个问题。 https://medium.com/@aashish.gaba097/database-seeding-with-large-files-in-laravel-be5b2aceaa0b
虽然,这是在Laravel,但是从csv中读取的代码是独立的(使用生成器的代码),逻辑可以在这里使用。