【问题标题】:Is there a faster way to import data from a file to MySQL using php?有没有更快的方法使用 php 将数据从文件导入 MySQL?
【发布时间】:2017-06-06 13:41:45
【问题描述】:

好的,所以我得到了大约 100k-1M 行的文本,我总是将它们导入数据库。我使用的代码如下:

$lines = new SplFileObject('/home/file.txt');
while(!$lines->eof()) {
    $lines->next();       //Skipping first line
    $row = explode(',',$lines);
    for($i = 0; $i<4; $i++){
        if(!isset($row[$i])){
            $row[$i] = null;
        }
    }
    $y = (float) $row[1];
    $z = (float) $row[2];
    $load_query = "INSERT IGNORE INTO new (datetime_gmt,field2,field3)
    VALUES ('".$row[0]."','".$y."','".$z."');";

    if(!$mysqli->query($load_query)){
      die("CANNOT EXECUTE".$mysqli->error."\n");
    }
}
$lines = null;

但是,它花费的时间太长了。有没有更快的方法,还是我坚持使用这种方法?

PS。我不想使用 MySQL 的“INSERT DATA INFILE”。

【问题讨论】:

  • 您只需要阅读 castis 引用的内容,但您还应该将批次限制为 20-50 个值(例如)
  • 您可以分块编写批量插入语句,以尽量减少对数据库的调用次数。如果你不关心插入数据库的顺序,那么你可以使用支持线程的语言如C(++,#)、Go、Rust、Java、D、Swift、Scala等... .
  • @castis 对不起,我很难找到这有什么帮助。我知道我可以使用插入添加多行,但是对于 100k 行我该怎么做呢?
  • 如何将数据插入数据库?在每个 $load_query 之后?

标签: php mysql splfileobject


【解决方案1】:

正如所写,您正在为每一行运行一个插入语句。如果您以INSERT INTO table (foo, bar) VALUES (1, 2), (3, 4), (5, 6); 的格式编译一个在最后执行一次的多插入语句,它会快得多。类似这样的东西,虽然它可以被清理得更多。

$lines = new SplFileObject('/home/file.txt');
$load_query = "INSERT IGNORE INTO new (datetime_gmt,field2,field3)
    VALUES ";
while(!$lines->eof()) {
    $lines->next();       //Skipping first line
    $row = explode(',',$lines);
    for($i = 0; $i<4; $i++){
        if(!isset($row[$i])){
            $row[$i] = null;
        }
    }
    $y = (float) $row[1];
    $z = (float) $row[2];
    $load_query .= "('".$row[0]."','".$y."','".$z."'),";
}

if(!$mysqli->query(rtrim($load_query, ','))) {
    die("CANNOT EXECUTE".$mysqli->error."\n");
}
$lines = null;

还要确保数据是可信的。如果文件可能来自外部用户,则直接附加到查询字符串会创建一个 SQL 注入向量。

【讨论】:

  • 是的,多插入会运行得更快。但是,请注意:mysql 有最大数据包大小限制(可在服务器上调整)。确保您的 sql 语句没有达到该限制。例如一次做 1000 行,然后是一个新的插入语句。如果您确实超过了该限制,则 sql 语句将损坏并且不会运行。
  • 使用事务也可能有所帮助。不如多插入多。
  • 我很确定这会奏效。我虽然达到了我的最大数据包大小,但我不允许增加它。例如,我如何使用@Zurahn 使用的代码一次将其设置为 1000?
  • 没关系,我使用 SplFileObject 中的 seek() 函数修复了它!非常感谢! :D
猜你喜欢
  • 2017-11-01
  • 1970-01-01
  • 2011-04-01
  • 1970-01-01
  • 2011-12-20
  • 1970-01-01
  • 2018-03-21
  • 1970-01-01
  • 2012-12-23
相关资源
最近更新 更多