2010-07-22 171 views
1

我有一个800MB的文本文件,其中有18,990,870行(每行是一条记录),我需要挑出某些记录,并且如果有匹配,则将它们写入数据库。如何加快处理一个巨大的文本文件?

它走的时代,通过他们的工作,所以我想知道是否有一种方法做任何更快?

我的PHP是一次读取一行如下:

$fp2 = fopen('download/pricing20100714/application_price','r'); 
if (!$fp2) {echo 'ERROR: Unable to open file.'; exit;} 
while (!feof($fp2)) { 
$line = stream_get_line($fp2,128,$eoldelimiter); //use 2048 if very long lines 
if ($line[0] === '#') continue; //Skip lines that start with # 
    $field = explode ($delimiter, $line); 
list($export_date, $application_id, $retail_price, $currency_code, $storefront_id) = explode($delimiter, $line); 
if ($currency_code == 'USD' and $storefront_id == '143441'){ 
// does application_id exist? 
$application_id = mysql_real_escape_string($application_id); 
$query = "SELECT * FROM jos_mt_links WHERE link_id='$application_id';"; 
$res = mysql_query($query); 
if (mysql_num_rows($res) > 0) { 
echo $application_id . "application id has price of " . $retail_price . "with currency of " . $currency_code. "\n"; 
} // end if exists in SQL 
} else 
{ 
// no, application_id doesn't exist 
} // end check for currency and storefront 
} // end while statement 
fclose($fp2); 
+0

谁是jos_mt_links表? 只需检索一次所有条目并在不访问数据库的情况下执行检查。 – Andreas 2010-07-22 14:24:23

回答

1

你被连续做两起爆炸分析输入线的两倍。

$field = explode ($delimiter, $line); 
list($export_date, ...., $storefront_id) = explode($delimiter, $line); 

另外,如果你只使用查询,测试根据您的情况相匹配,不要使用SELECT *使用这样的:我会通过去除前行启动

"SELECT 1 FROM jos_mt_links WHERE link_id='$application_id';" 

正如Brandon Horsley所建议的,您也可以将一组application_id值缓存在数组中,并将您的select语句修改为使用IN子句,从而减少正在执行的查询数。

8

在猜测,性能问题,是因为它发出与美元,你的店面每APPLICATION_ID查询。

如果空间和IO是不是一个问题,你可能只是盲目地写所有19M记录到一个新的临时数据库表,添加索引,然后做一个过滤器匹配?

+0

确实读取每一行并写入数据库,然后排序将花费尽可能多的时间来读取每一行,并只写入我想要的数据库? – kitenski 2010-07-22 13:46:07

+3

@kitenski:你试过了吗?我的意思是,这只是大约10行代码。 做19M顺序,异步插入将比19M随机选择更快。 – Andreas 2010-07-22 14:23:29

3

不要试图发明车轮,它已经完成。使用数据库搜索文件的内容。您可以将该文件装载到数据库中的临时表中,并使用索引查询数据以便快速访问(如果它们增加了值)。大多数(如果不是全部)数据库都有导入/加载工具,可以相对较快地将文件导入数据库。

+0

确实读取每一行并写入数据库,然后排序将花费尽可能多的时间来读取每一行,并只写入我想要的数据库? – kitenski 2010-07-22 13:55:15

+0

不读取每一行并写入数据库,但利用大多数数据库一次性批量加载文件的工具。之后,您可以选择添加任何所需的索引,最后通过选择/插入到数据库表中来搜索您关心的数据。 – Kuberchaun 2011-12-12 02:21:55

0

数据库是为了处理大量数据而构建和设计的,PHP不是。您需要重新评估您如何存储数据。

我将转储所有记录到数据库中,然后删除你不需要的记录。完成之后,您可以随时随地复制这些记录。

2

如果数据库设计不正确,数据库上的19M行会减慢速度。如果分区正确,您仍然可以使用文本文件。基于某些参数重新创建多个较小的文件,以适当的排序方式存储可能会奏效。

反正PHP不是文件IO和处理最好的语言,它比Java更慢了这个任务,而普通的老式C将是最快的工作之一。 PHP应该限制为生成动态Web输出,而核心处理应该使用Java/C。理想情况下,它应该是生成输出的Java/C服务,以及使用该提要生成HTML输出的PHP。

1

你试过剖析代码,看看它是花费了大量的时间?这应该始终是您尝试诊断性能问题时的第一步。

0

正如其他人所提到的,费用可能在您的数据库查询。从文件加载一批记录(而不是一次一个)并执行一个查询来检查多个记录可能会更快。在一个时间匹配的美元货币和店面成阵列,并执行类似的查询

例如,负载1000记录:

'select link_id from jos_mt_links where link_id in (' . implode(',', application_id_array) . ')'

这将返回的那些在记录的列表数据库。或者,您可以将sql更改为not in以获取不在数据库中的那些记录的列表。

1

用sed和/或awk预处理?