导入140万行800mb制表符分隔文件的最佳方法是什么?

时间:2014-09-30 00:37:57

标签: php mysql phpmyadmin

我有一个800mb制表符分隔文件,有140万条记录需要进入MySQL数据库。在我运行任何削弱我本地机器的东西之前,我想知道最好的方法是什么。当我获得包含更新数据的新文件时,我将需要每4-6周执行一次此操作。

我一直在想以下其中一项可能是最好的,但我不确定:

选项1

$input = file('data-file.tab', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);

$filedata= array();

foreach ($input AS $line) {

    $data = explode("\t", $line);

    // function to import data to MySQL

}

选项2

将文件拆分为可管理的块并通过phpMyAdmin导入。

4 个答案:

答案 0 :(得分:3)

我不会通过phpmyadmin这样做。我知道这可能是您更熟悉的界面,但如果您要管理工业大小的数据集,您应该习惯使用更高效和可靠的其他工具。

转到命令行并使用mysqlimport。这是LOAD DATA statement的命令行界面。您可以在客户端主机上执行此操作并远程导入,也可以将文件上载到数据库服务器并在本地导入。

要拆分文件,请使用pt-fifo-split。这样可以轻松地在文件块上编写shell循环,而无需将文件物理地拆分为多个较小的文件。

答案 1 :(得分:1)

第1步:使用正确的工具完成工作。如果要将数据导入数据库,请将数据转换为数据库可读形式,然后以明显的方式将其导入数据库(即使用数据库的导入功能)。

您可以使用PHP编写一个小脚本,该脚本将逐行运行数据文件并将其转换为您需要的SQL表单,并将其写入out.sql文件,然后您可以将其正常导入到您的文件中D B。完成。在事务开始/结束调用中包装你的out.sql,使得导入的奖励点数快了百万倍。

答案 2 :(得分:0)

因为它有800MB,你当然不希望一次将整个文件加载到内存中,所以file()不是一个选项。相反,你应该逐行阅读。

你可以用两种基本方式做到这一点。首先,您将使用以下命令创建文件描述符以读取此文件:

$fd = fopen('data-file.tab', 'r');

现在您有两个选项来遍历此文件的行:

选项1:使用fgets()读取每一行。它将包含行分隔符,因此请记住trim()之前的explode()

示例:

while ($line = fgets($fd))
{
    $line = explode("\t", trim($line));
    // do what you must with it
}

选项2:它是简单的制表符分隔还是类似CSV的文件?您可以考虑在最后一种情况下使用fgetcsv()

while ($line = fgetcsv($fd, 0, "\t"))
{
    // $line is already ready and formatted, do what you must with it
}

其他性能注意事项

内存问题已解决,但在MySQL中包含这些记录可能非常耗时,特别是如果您要直接从PHP运行MySQL查询。有几种方法可以促进这一点。

首先,不要分别INCLUDE每一行。不要为每条记录生成INSERT INTO table...,而是考虑缓冲记录并将其插入到每个INSERT查询的100个或更多的包中。这将加速很多事情。

为了提高速度,您可以将数据库部件外包给并行进程,在本例中为mysql控制台客户端本身。如果您运行使用mysqli_*等MySQL扩展程序生成的查询,则只需echo它们或将其发送到使用mysql创建的popen()进程。

示例:

$ php generate_queries.php | mysql -u user -ppassword database

或者使用popen()

在PHP代码中完成所有操作
$mysql = popen('mysql -u user -ppassword database', 'w');
...
fwrite($mysql, 'INSERT INTO table...');

答案 3 :(得分:0)

简短的回答是您需要担心您的计算机以及要将记录导入的MySQL服务器。

在尝试下面之前,您希望在MySQL上进行优化配置(包括重新启动mysql以进行my.cnf更改)。

完成后,您需要查看LOAD DATA INFILE MySQL命令。

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

示例:

LOAD DATA INFILE 
  '/tmp/test.txt' 
INTO TABLE 
  testTable
FIELDS TERMINATED BY 
  ','  
LINES TERMINATED BY 
  '\r\n'  -- Windows created file
ENCLOSED BY 
  '"' 
IGNORE 
  1 LINES
(col1, col2, col3, col4, col5...)