我正在使用50 Gb MySQL导出文件,并对其执行脚本操作列表以转换为SQLite3可加载形式(我从这里得到的线索:脚本将mysql dump sql文件转换为可以导入sqlite3的格式D b )。我尚未研究MySQL转储的结构,数据是从第三方获得的。我可以看到它具有创建表并插入到语句中的功能,但是鉴于其大小,很难手动阅读并理解其结构。
由于大小原因,无法通过管道传输文件。还有一个bash脚本,用于加载文件,然后逐行处理,例如
while read line
抱怨说它的内存不足。
因此,我尝试使用awk或sed来选择每一行(两者均起作用),将该行写入文件,然后将其通过perl脚本列表。这是我正在使用的awk脚本
$ awk -vvar="$x" 'NR==var{print;exit}' file > temp
其中x保留行号,然后通过perl命令发送temp,最后将它们附加到输出文件中。
但是,尽管最初速度很快,但是由于开始必须遍历越来越多的行,因此它很快会变慢。大约有40,000行。
有没有人像这样工作?有更快的方法吗?
为什么脚本必须遍历越来越多的行?我猜您没有40000个文件,每个文件仅包含一行,但是您能否提供更多详细信息?
命令$ sed -n 10 {p; q} file,将读取前9个,并给我第10行并退出sed。随着数量增加到40,000,它必须遍历更多行才能给我特定的行。
好的,我知道了。是否可以选择先将文件分割成50个1Gb文件?然后对每个块进行处理,最后再次加入这些块。
我在超级计算机上可以拥有的文件数量受到限制,因此尽管50个文件太多,我还是可以尝试获得一个最大数量的文件,该数量将好于1个。谢谢您的指导。
也许您也可以发布正在使用的脚本? (如果很大,您可以尝试将其上传到pastebin.com并在此处提供链接)。
如果您给出了所需的MySQL导出数据和SQLite3可加载格式的示例,那么这似乎是一个更多人可以帮助的问题。我假设您希望从输入中读取的每一行MySQL都输出一行SQLite数据?您链接到的解决方案对我来说似乎很可怕,而且我相信它可以用单个Perl程序编写。
您正在MySQL中执行SELECT * FROM table INTO OUTFILE table.txt,然后在SQLite中执行.import table.txt table?
我还没有编写MySQL转储,也没有完全按照文件的大小来遵循结构。该问题已更新以反映这一点。此外,尽管sqlite3仍然抱怨格式,但建议将文件拆分为脚本有效。谢谢!
一次只需处理一行:
while read -r line
do
echo"$line"> temp
…process temp with Perl, etc…
done < file
至少这不会表现出二次读取文件的行为,这就是您的awk脚本所做的。
它只读取一次大文件,这是Big-O表示法的最佳性能(在恒定因子内)。
如您所说,如果这导致bash出现问题,则应使用Perl读取每一行。 在50 GiB数据中有40,000行,您大约有1个? 每行数据的MiB。 尽管可能会导致Bash问题,但这不太可能导致Perl出现任何问题。 您可以修改现有的Perl一次读取一行,也可以使用简单的包装Perl脚本来完成上述Bash脚本的工作。
wrapper.pl
假设您当前的处理脚本称为script.pl:
#!/usr/bin/env perl
use strict;
use warnings;
my $file ="temp";
while (<>)
{
open my $fh,">", $file or die;
print $fh $_;
close $fh;
system"perl","script.pl", $file;
}
未经测试的代码
调用:
perl wrapper.pl output