如何优化此 sql 插入 php 代码?

how to optimize this sql insertion php code?

我有 mysql 数据库,我想从 PHP 代码中插入大约 40'000 行,但我的代码需要超过 15 分钟才能插入这些行,有机会优化吗?我的问题在哪里(PHP代码/数据库设计)?

详情如下:

- 行数据 存储在一个 utf-8 txt 文件中,值由“\t”制表符分隔,每一行集在文件的一行中,例如这个

字符串视图:

"value1\tvalue2\tvalue3\value4\value5\r\nvalue1\tvalue2\tvalue3\value4\value5\r\nvalue1\tvalue2\tvalue3\value4\value5\r\nvalue1\tvalue2\tvalue3\value4\value5\r\n"

文本reader视图:

value1     value2     value3     value4     value5
value1     value2     value3     value4     value5
value1     value2     value3     value4     value5
value1     value2     value3     value4     value5

-数据库有3个table是这样的:

table1 countries fields(1) (NAME varchar -primarykey-)
table2 products fields(2) (HS varchar - primarykey-, NAME varchar) 
table3 imports fields (6) (product_hs varchar -foreignkey->products(HS),
counteryname varchar - foreignkey->countries (NAME),
year year,
units int,
weight int,
value int)        

- php 代码 是这样的

$conn = new mysqli($hn,$un,$pw,$db);
if($conn->connect_error) {die($conn->connect_error);}

$x = 0; // row counter
ini_set('max_execution_time', 3000);

while(!feof($filehandle)){
$x++;
echo $x . ":  ";
$fileline = fgets($filehandle);
$fields = explode("\t", $fileline);
$query = "INSERT INTO imports(product_hs,counteryname,year,units,weight,value) VALUES(" . "'" . $fields[0] ."','". $fields[1] . "','2014','". $fields[2] . "','" . $fields[3] . "','" . $fields[4] .  "');";
$result = $conn->query($query);
if(!$result) {
    echo $conn->error . "</br>";
}else{
    echo $result . "</br>";
}
};

起初我以为是索引问题导致插入变慢,所以我把"imports"table中的所有索引都去掉了,但是并没有变快!! 是数据库设计的问题还是我的 php 代码的问题?

另请注意,浏览器在前 5 分钟通知 "waiting for response from the server",然后大部分剩余时间通知 "transferring data from server",这是因为响应 html 行计数器 1:1 </br> 2:1 </br> ..... 有超过 40'000 行(在 php 代码中声明)?

请考虑我是新手,谢谢。

非常感谢tadman and Hanlet Escaño and Uueerdo and Julie Pelletier and Solarflare 在评论中帮助我。

我使用您在评论中建议的方法对 PHP 代码进行了 3 处不同的更改,然后我测试了结果,这里是测试结果。

3 次测试的结论: 正如 tadman 所建议的,关键在 LOAD DATA INFILE 中。它大大减少了执行时间,不到 7 秒,这些是 3 个测试。


原始代码: ~ 26 分钟


测试 1: ~ 34 分钟

(正如 Uueerdo 建议我从循环中删除了 echo 语句和行计数器)

while(!feof($filehandle)){
// $x++; // commented out
//echo $x . ":  "; // commented out
$fileline = fgets($filehandle);
$fields = explode("\t", $fileline);
$query = "INSERT INTO products(hs,arabicname,englishname) VALUES(" . "'" . str_replace("'", ".", $fields[0]) ."'," . "'". str_replace("'", ".", $fields[1]) . "'," . "'". str_replace("'", ".", $fields[2]) . "');"; 
$result = $conn->query($query); 
/* // commented out
if(!$result) {echo  $conn->error . "</br>";}
}else{echo $result . "</br>";}
*/};

测试 2: ~ 7 秒

(正​​如tadman所说 我搜索了LOAD DATA INFILE 超级强大

//replace the entire loop with this simple query
$query = "LOAD DATA LOCAL INFILE'" . 
addslashes("C:\xampp\htdocs\bots\impandexp\imports.txt")
. "' INTO TABLE imports FIELDS TERMINATED BY '\t' LINES TERMINATED BY
'\r\n'(product_hs,counteryname,units,weight,value) SET  year = '2014';";
 $result = $conn->query($query);

测试 3: ~ 5 秒

它与测试 2 相同,只是我在 tadman 提供的同一页面上找到了有用的提示,有助于最大限度地提高速度。

Bulk Data Loading for InnoDB Tables

// turning off index checks that might slows down bulk data insertion
$query = "SET foreign_key_checks=0;";
$conn->query($query);
$query = "SET unique_checks=0;";
$conn->query($query);
$query ="SET autocommit=0;";
$conn->query($query);

$query = "LOAD DATA LOCAL INFILE'" . addslashes("C:\xampp\htdocs\bots\impandexp\imports.txt") . "' INTO TABLE imports FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\r\n'(product_hs,counteryname,units,weight,value) SET  year = '2014';";
$result = $conn->query($query);
echo $result . "</br>";
// turning them on again
$query = "SET foreign_key_checks=1;";
$conn->query($query);
$query = "SET unique_checks=1;";
$conn->query($query);
$query ="COMMIT;";
$conn->query($query);