Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/290.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP+MySQL:大CSV文件导入_Php_Mysql_Sql_Csv_Zend Framework - Fatal编程技术网

PHP+MySQL:大CSV文件导入

PHP+MySQL:大CSV文件导入,php,mysql,sql,csv,zend-framework,Php,Mysql,Sql,Csv,Zend Framework,我正在尝试加速这个脚本,以便将CSV文件导入MySQL。 对于1000行,加载它需要130秒。尝试将其用于30000行,20分钟后超时并加载8681行 CSV标题看起来可以是任意顺序的任意数量的列: email;param1;..;paramX test@test.com;something;..;value MySQL创建邮件队列: CREATE TABLE IF NOT EXISTS `mail_queue` ( `mail_queue_id` INT NOT NULL AUTO_I

我正在尝试加速这个脚本,以便将CSV文件导入MySQL。 对于1000行,加载它需要130秒。尝试将其用于30000行,20分钟后超时并加载8681行

CSV标题看起来可以是任意顺序的任意数量的列:

email;param1;..;paramX
test@test.com;something;..;value 
MySQL创建邮件队列:

CREATE TABLE IF NOT EXISTS `mail_queue` (
  `mail_queue_id` INT NOT NULL AUTO_INCREMENT,
  `mailer_batch_id` INT NOT NULL,
  `to` VARCHAR(100) NOT NULL,
  `priority` INT NOT NULL DEFAULT 0,
  `created` DATETIME NOT NULL DEFAULT NOW(),
  `mail_status_id` INT NOT NULL,
  PRIMARY KEY (`mail_queue_id`),
  INDEX `fk_mail_queue_mailer_batch1_idx` (`mailer_batch_id` ASC),
  INDEX `fk_mail_queue_mail_status1_idx` (`mail_status_id` ASC),
  CONSTRAINT `fk_mail_queue_mailer_batch1`
    FOREIGN KEY (`mailer_batch_id`)
    REFERENCES `mailer_batch` (`mailer_batch_id`)
    ON DELETE CASCADE
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_mail_queue_mail_status1`
    FOREIGN KEY (`mail_status_id`)
    REFERENCES `mail_status` (`mail_status_id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;
MySQL创建邮件参数:

CREATE TABLE IF NOT EXISTS `mail_param` (
 `mail_param_id` INT NOT NULL AUTO_INCREMENT,
 `mail_queue_id` INT NOT NULL,
 `param_key` VARCHAR(45) NOT NULL,
 `param_value` VARCHAR(45) NOT NULL,
 PRIMARY KEY (`mail_param_id`),
 INDEX `fk_mail_param_mail_queue1_idx` (`mail_queue_id` ASC),
  CONSTRAINT `fk_mail_param_mail_queue1`
  FOREIGN KEY (`mail_queue_id`)
  REFERENCES `mail_queue` (`mail_queue_id`)
  ON DELETE CASCADE
  ON UPDATE NO ACTION)
 ENGINE = InnoDB;
代码Zend框架。工作正常,但速度较慢:

    if (($handle = fopen($this->filepath, 'r')) !== false)
    {
        // DB
        $mailQueueTable = new Application_Model_DbTable_MailQueue();
        $mailParamTable = new Application_Model_DbTable_MailParam();

        // Get header
        $header = \ForceUTF8\Encoding::toUTF8(fgetcsv($handle, 0, ';'));

        while(($data = fgetcsv($handle, 0, ';')) !== false)
        {
            // Save e-mail to e-mail queue 
            $mailQueueRow = $mailQueueTable->createRow();
            $mailQueueRow->mailer_batch_id = $mailerBatchId;
            $mailQueueRow->to = $data[$this->emailColumn];
            $mailQueueRow->priority = 0;
            $mailQueueRow->created = $created->toString('yyyy-MM-dd HH:mm:ss');
            $mailQueueRow->mail_status_id = 1;
            $mailQueueId = $mailQueueRow->save();

            // Save e-mail params
            foreach ($data as $key => $value) {
                $mailParamRow = $mailParamTable->createRow();
                $mailParamRow->mail_queue_id = $mailQueueId;
                $mailParamRow->param_key = $header[$key];
                $mailParamRow->param_value = \ForceUTF8\Encoding::toUTF8($value);
                $mailParamRow->save();
            }

            unset($data);
        }
        fclose($handle);

    }
我尝试将数据加载到中,但由于mail_param表结构,我无法使用它

1创建临时表OK

2加载数据填充正常

3插入到邮件队列中确定

4插入邮件参数

我不知道在这里写什么。我需要为tmp_csv_导入表中的每一列插入新行。我需要获取mail_queue_id-表mail_参数的外键

$query = "INSERT INTO mail_param (mail_queue_id, param_key, param_value) 
SELECT ??? FROM `tmp_csv_import`";

在MySQL中有可能做到这一点吗?或者我应该用不同的方法来解决这个问题?

我找到了解决问题的方法。不需要使用临时表

1将使用以下代码加载到邮件队列的数据:

$query = "LOAD DATA INFILE '" . $this->filepath . "'
INTO TABLE `mail_queue`
FIELDS TERMINATED BY ';'
ENCLOSED BY '\"'
LINES TERMINATED BY '\n'
IGNORE 1 ROWS
(@dummy, @dummy, email, @dummy)
SET `mailer_batch_id` = " . (int) $mailerBatchId . ",
    `priority` = 0,
    `created` = NOW(),
    `mail_status_id` = 1;";
对于仅导入一行,将由标题生成

(@dummy, @dummy, email, @dummy)
其他值将按set设置

2我将从插入的值中选择mail_queue_id,并将其插入此样式的数组中:

array('to' => 'mail_queue_id');
3我将从源文件创建临时CSV文件。结构:

mail_queue_id;key;value
4数据将加载到邮件参数表中:

$query = "LOAD DATA INFILE " . $tmpFilepath . "
    INTO TABLE `mail_param`
    FIELDS TERMINATED BY ';'
    ENCLOSED BY '\"'
    LINES TERMINATED BY '\n'
    (`mail_queue_id`, `param_key`, `param_value`);";
五,


完成了。我尝试加载30000行的CSV,速度明显加快1s.

我不知道$mailerBatchId从哪里来。即使您对上次插入的id进行了注释//$mailerBatchId。使用tmp\u csv\u导入的id作为邮件批处理id和邮件队列id会更容易。它是否适合您的任务?
array('to' => 'mail_queue_id');
mail_queue_id;key;value
$query = "LOAD DATA INFILE " . $tmpFilepath . "
    INTO TABLE `mail_param`
    FIELDS TERMINATED BY ';'
    ENCLOSED BY '\"'
    LINES TERMINATED BY '\n'
    (`mail_queue_id`, `param_key`, `param_value`);";
unlink($tmpFilepath)