【问题标题】:How to faster Mysql Insert with nullif?如何使用 nullif 加快 Mysql 插入速度?
【发布时间】:2018-03-14 14:25:43
【问题描述】:

我正在通过 PHP 加载一个 CSV 文件并插入到一个临时表中,这就是我加载 PHP 脚本和 MySQL 查询的内容。

    $i=0;
    while (($data = fgetcsv($source, 1000, ",")) !== FALSE)
        {   
            if($i!=0) {
                $column1=$data[0];
                $column2=$data[1];
                $column3=$data[2];
                $column4=$data[3];
                $column5=$data[4];
                $column6=$data[5];
                $query= "INSERT INTO temp_table(column1,column2,column3,column4,column5,column6,load_datetime)
    VALUES (nullif('$column1',''), nullif('$column2',''), nullif('$column3',''), nullif('$column4',''), nullif('$column5',''), nullif('$column6',''),now())";
                mysql_query($query) or die(mysql_error());
            }
            $i++;
        }

我的 CSV 文件有 25000 条记录, 这是我的 CSV 中的示例行

        column1,column2,column3,column4,column5,column6
        ,,,13:57:18,,23:00:19

我面临的问题是,加载 CSV 需要 10 多分钟,而页面之间则变为空白。 我的 PHP 设置:upload_max_filesize:100M post_max_size:100M max_execution_time:1000 max_input_time:1000。

这是我的餐桌详情

   CREATE TABLE temp_table (
       id int(11) NOT NULL,
       column1 time DEFAULT NULL,
       column2 time DEFAULT NULL,
       column3 time DEFAULT NULL,
       column4 time DEFAULT NULL,
       column5 time DEFAULT NULL,
       column6 time DEFAULT NULL,
       load_datetime datetime DEFAULT NULL
   ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

当我检查 temp_table 时,它​​已插入大约 8000 条记录。请帮助我更快地插入。

【问题讨论】:

    标签: php mysql csv php-ini nullif


    【解决方案1】:

    我会建议你停止使用 mysql 扩展 (mysql_*)
    并开始使用mysqliPDO

    尝试将几行的数据分组到一个查询中。

    例子:

    $i  = 0;
    $i2 = 0;
    $sql = "INSERT INTO temp_table(column1,column2,column3,column4,column5,column6,load_datetime) VALUES ";
    $values = [];
    while (($data = fgetcsv($source, 1000, ",")) !== FALSE) {
        if(++$i == 1)
            continue;
        else {
            $data = array_map(function($item) {
                return $item == '' ? 'NULL' : "'$item'";
            }, $data);
            $values[] = "(" . implode(", ", $data) . ', now()' . ")";
            if (++$i2 == 500) {
                mysql_query ($sql . implode(', ', $values)) or die(mysql_error());
                $values = [];
                $i2 = 0;
            }
        }
    }
    if (!empty($values)) {
        mysql_query ($sql . implode(', ', $values)) or die(mysql_error());
        $values = [];
    }
    

    【讨论】:

    • 以前我忘记添加now() 现在试试。如果没有帮助,尝试输出生成的sqlecho $sql . implode(', ', $values)
    • 您的解决方案只用了不到 2 分钟,并插入了 25000 条记录。非常感谢。
    • @davidb 1if(++$i == 1) continue;` 跳过第一行 (-;
    【解决方案2】:

    我认为 PHP 脚本需要一些时间。试试下面的代码,让我知道它改进了多少,并且您可以一次将 50 到 100 条记录分组。

     while (($data = fgetcsv($source, 1000, ",")) !== FALSE)
    {   
    if($i!=0)
    {
    $query= "INSERT INTO temp_table(column1,column2,column3,column4,column5,column6,load_datetime)
    VALUES (nullif('$data[0]',''), nullif('$data[1]',''), nullif('$data[2]',''), nullif('$data[3]',''), nullif('$data[4]',''), nullif('$data[5]',''),now())";
    mysql_query($query) or die(mysql_error());
    }
    $i++;
    }
    

    【讨论】:

    • 谢谢你,我试过了,和以前一样。
    • 我能知道直接在数据库中执行和用php代码写的一样需要多少时间吗?
    • 同样在创建表代码中,id应该是自增字段或者它应该有默认值。
    • 如果查询执行不需要更多时间,那么您可以阅读以下文章。 stackoverflow.com/questions/6245971/… 通过这个你可以知道 PHP 代码在哪里花费了更多的时间。
    • 表中id字段为主键,设置为自增。
    猜你喜欢
    • 1970-01-01
    • 2013-08-29
    • 2017-11-19
    • 2012-10-26
    • 2013-04-03
    • 1970-01-01
    • 2012-05-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多