使用PHP将CSV数据导入MySQL数据库


csv data import into mysql database using php

嗨,我需要导入一个 15000 行的 csv 文件。我正在使用 fgetcsv 函数并解析每一行。但是我每次都收到超时错误。该过程太慢,数据被部分导入。有什么办法可以使数据导入更快、更高效吗?

if(isset($_POST['submit']))
{
 $fname = $_FILES['sel_file']['name'];
 $var = 'Invalid File';
 $chk_ext = explode(".",$fname);
 if(strtolower($chk_ext[1]) == "csv")
 {
     $filename = $_FILES['sel_file']['tmp_name'];
     $handle = fopen($filename, "r");
 $res = mysql_query("SELECT * FROM vpireport");
 $rows = mysql_num_rows($res);
 if($rows>=0)
{
    mysql_query("DELETE FROM vpireport") or die(mysql_error());
    for($i =1;($data = fgetcsv($handle, 10000, ",")) !== FALSE; $i++)
    {
        if($i==1)
        continue;
        $sql = "INSERT into vpireport
                                (item_code,
                                 company_id,
                                 purchase,
                                 purchase_value) 
                                 values
                                (".$data[0].",
                                 ".$data[1].",
                                 ".$data[2].",
                                 ".$data[3].")";
        //echo "$sql";
        mysql_query($sql) or die(mysql_error());
    }
}
 fclose($handle);
?>
 <script language="javascript">
 alert("Successfully Imported!");
 </script>
 <?

}问题是每次它卡在导入过程之间并显示以下错误:

错误 1 :致命错误:第 175 行超过了 30 秒的最大时间限制。

错误 2 :

您的 SQL 语法有错误;请查看与您的 MySQL 服务器版本对应的手册,了解在第 1 行的"S",0,0("附近使用的正确语法

这个错误我无法检测到...

该文件每次都导入 oly 部分.. oly 大约 200 300 行中的 10000 行。.

您可以为每 500 行 csv 构建一个批量更新字符串,然后在每行上执行 mysql 插入,请立即执行它。它会更快。

另一种解决方案是读取带有偏移量的文件:

  1. 阅读前 500 行,
  2. 将它们插入数据库
  3. 重定向至"csvimporter.php?offset=500
  4. 返回 1. 步长并读取这次从偏移量 500 开始的 500 行。

另一种解决方案是将超时限制设置为 0,如下所示:

set_time_limit(0);

在页面顶部设置此项:

set_time_limit ( 0 )

它将使页面无休止地运行。但是,不建议这样做,但如果您没有其他选择,那就帮不上忙了!

您可以在此处查阅文档。

为了使其更快,您需要检查您正在发送的各种 SQL,并查看您是否创建了正确的索引。

如果您正在调用用户定义的函数,并且这些函数引用全局变量,则可以将这些变量传递给函数并更改代码以使函数引用这些传递的变量来最大程度地减少所花费的时间。引用全局变量比局部变量慢。

您可以使用 LOAD DATA INFILE 这是一个 mysql 实用程序,这比 fgetcsv 快得多

更多信息请访问

http://dev.mysql.com/doc/refman/5.1/en/load-data.html

只需在 PHP 导入页面的开头使用 @

ini_set('max_execution_time',0);

问题:
对将数据插入表的方式有巨大的性能影响。对于您向服务器发送的每条记录,15000 个插入请求是巨大的!

解决方案::
好吧,你应该像mysqldump那样对数据进行分组。在您的情况下,您只需要三个插入语句而不是 15000,如下所示:

在循环写入之前:

$q = "INSERT into vpireport(item_code,company_id,purchase,purchase_value)values";

在循环中将记录连接到查询,如下所示:

$q .= "($data[0],$data[1],$data[2],$data[3]),";

在循环中检查计数器是否等于 5000 或 10000 或 15000,然后将数据插入vpireprot表中,然后将$q再次设置为 INSERT INTO...
运行查询并享受!!

如果这是一次性练习,PHPMyAdmin 支持通过 CSV 导入。import-a-csv-file-to-mysql-via-phpmyadmin

他还指出了利用MySQL LOAD DATA LOCAL INFILE的用户。这是将数据导入数据库表的非常快速的方法。加载数据 Mysql 文档链接

编辑:

下面是一些伪代码:

// perform the file upload 
$absolute_file_location = upload_file();
// connect to your MySQL database as you would normally
your_mysql_connection();
// execute the query
$query = "LOAD DATA LOCAL INFILE '" . $absolute_file_location . 
         "' INTO TABLE `table_name`
         FIELDS TERMINATED BY ','
         LINES TERMINATED BY ''n'
         (column1, column2, column3, etc)";
$result = mysql_query($query);

显然,您需要确保良好的SQL实践以防止注入等。