我有一个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导入。
答案 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()
:
$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...)