我有一个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 :(得分:8)
据猜测,性能问题是因为它为每个带有USD和店面的application_id发出查询。
如果空间和IO不是问题,您可能只是盲目地将所有19M记录写入新的临时数据库表,添加索引然后与过滤器匹配?
答案 1 :(得分:3)
不要试图发明轮子,它已经完成了。使用数据库搜索文件的内容。您可以将该文件挂载到数据库中的临时表中,并使用索引查询数据,以便在增加值时快速访问。大多数(如果不是所有)数据库都有导入/加载工具来相对快速地将文件导入数据库。
答案 2 :(得分:2)
答案 3 :(得分:1)
您是否尝试过分析代码以查看其大部分时间花在哪里?在尝试诊断性能问题时,这应该始终是您的第一步。
答案 4 :(得分: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子句,从而减少您正在执行的查询数量。
答案 5 :(得分:1)
使用sed和/或awk进行预处理?
答案 6 :(得分:0)
数据库的构建和设计是为了处理大量数据,PHP则不然。您需要重新评估存储数据的方式。
我会将所有记录转储到数据库中,然后删除不需要的记录。完成后,您可以将这些记录复制到任何地方。
答案 7 :(得分:0)
正如其他人所提到的,费用可能在您的数据库查询中。从文件中加载一批记录(而不是一次一个)可能会更快,并执行一个查询来检查多个记录。
例如,将一次与USD货币和店面匹配的1000条记录加载到数组中并执行如下查询:
'select link_id from jos_mt_links where link_id in (' . implode(',', application_id_array) . ')'
这将返回数据库中记录的列表。或者,您可以将sql更改为not in
以获取不在数据库中的那些记录的列表。