【发布时间】:2019-06-29 04:35:02
【问题描述】:
我有一个 5M 行的 csv。我可以选择在 mysql 数据库中导入它们 然后用php循环表格。
db_class=new MysqlDb;
$db_class->ConnectDB();
$query="SELECT * FROM mails WHERE .....";
$result=mysqli_query(MysqlDb::$db, $query);
while($arr=mysqli_fetch_array($result))
{
//db row here
}
所以我从表中循环所有邮件并处理它们。如果它们包含一些错误的字符串,我会删除它们等。
这可行,但导入 5M 行非常慢,将所有行逐一循环并编辑行也非常慢(当它们包含错误字符串时删除)。
我正在考虑一个更好的解决方案来完全跳过 php/mysql。我将逐行处理 .csv 文件并检查当前行是否包含特定的错误字符串。我可以在纯 php 中做到这一点,例如:
$file = file('file.csv');
while (($data = fgetcsv($file)) !== FALSE) {
//process line
$data[0];
}
这是我用来循环文件所有行的 bash 脚本
while read line; do
sed -i '/badstring/d' ./clean.csv
done < bac.csv
我在 python 上做
with open("file.csv", "r") as ins:
array = []
for line in ins:
//process line here
一条不好的线就像
name@baddomain.com
name@domain (without extension)
等等我有几个标准来判断什么是坏行,这就是为什么我没有费心在这里发布它的原因。
但是对于非常大的文件,我必须尝试找到更好的解决方案。大家有什么推荐的?我应该学习如何在 c/c++ 或 bash 中做到这一点。 Bash 我已经知道一点,所以我可以让它更快。在这种情况下,c/++++ 是否比 bash 快得多?或者我应该坚持使用 bash?
谢谢
【问题讨论】:
-
»如果当前行包含特定的错误字符串«。最好的解决方案取决于坏字符串到底是什么。如果可以通过简单的正则表达式识别坏字符串,我将在 bash 或任何其他 shell 中使用单个
grep调用。请在删除坏行之前和之后发布一个小示例文件。 -
不要将所有行读入内存,而是考虑在 C (++) 代码中逐行处理文件。由于您尚未发布任何相关代码,因此我推荐 Perl:
perl -MText::CSV_XS=csv -e 'open my $fh, '<', "file.csv" or die $!; my $csv = Text::CSV_XS->new(); while (my $line = $csv->getline($fh) { ... })。见Text::CSV_XS -
@Corion 我提到我不懂 C++。如果我必须为这项任务学习它,(如果它的速度值得,我会做 s0
-
PHP The manual
fgetcsv()一次读取一行而不是一口气读取整个文件 -
在您的
bash脚本中,您正在为每一行创建一个新的sed子进程——我看不出这是多么必要。它肯定会对性能产生影响。请记住bash支持正则表达式,并且通常不需要外部sed语言。 C 或 C++ 可能会提高性能,但如果不测量性能瓶颈在哪里,则无法保证。为此使用strace之类的东西。一般来说,C 或 C++ 必须写得好,很容易写出糟糕的代码,这会产生比解决的问题更多的问题。