1

クライアントは金融サービスのウェブサイトを持っており、毎朝リードでいっぱいのCSVスプレッドシートを入手しています。通常、各シートには約10k〜15kのレコードがあります。彼がやりたいのは、そのスプレッドシートをアップロードし、サーバーにそれを解析させ、データベースに重複するリードがないかチェックし、それらをデータベースに挿入し、外部APIに対してレコードをチェックし、適格なリードを電子メールで送信することです。

今、私は彼にこれらすべてを行うその場しのぎのユーティリティを構築しましたが、サーバーとデータベースはこれを何度も実行することで過度のストレスがかかっているように見えます。彼はそれらを1000レコードパケットに分割する必要がありますが、これは彼を悩ませます。ファイルをアップロードし、スプレッドシートをループして、一度にそれほど多くを処理できないことを除いて、上記のすべてを実行します。

だから私の質問は、あなたがこのようなものをどのように扱うことができるかについて誰かが一般的なアドバイスを持っているか、あなたがこのようなものについて考えるかもしれないことはありますか?特に、1つのファイルをアップロードして、その日の残りの時間はそれについて心配する必要がないことは、彼の顔に大きな笑顔をもたらすでしょう。

これが私が現在これらのレコードを処理している方法です(笑わないでください):

<?php
//standard php file upload handler
include("upload.inc.php");

$conn = mysql_connect("localhost","username","password");

mysql_select_db("database",$conn);



if($_FILES['csvFile']['name']) {

$upload_dir = $_SERVER['DOCUMENT_ROOT'] . "/upload/files/";

list($file,$errMsg) = upload('csvFile',$upload_dir,'');



// clear the db table

$sql = "DELETE FROM tempTable";

$result = mysql_query($sql) or die("Error: " . mysql_error() . "<br>");



// process the file

$row = 1;

$fileName = $upload_dir . $file;

if (($handle = fopen($fileName, "r")) !== FALSE) {

while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {

$num = count($data);

// write the data to mysql duplicate checker table

$sql = "INSERT INTO tempTable (process_date,firstname,middlename,lastname,ssn,dob,dl_number,dl_state,gender,military_active,amount_requested,residence_type,residence_length,address1,address2,city, state,zip,phone_home,phone_cell,contact_time,email,ip_addr,pay_frequency,net_income,first_payday,second_payday,employment_status,employer_name,job_title,hire_date,phone_work,phone_work2, bank_name,account_type,direct_deposit,reference1_firstname,reference1_lastname,reference1_relationship,phone_reference1,reference2_firstname,reference2_lastname,reference2_relationship, phone_reference2,routing_no,account_no) VALUES

('".mysql_escape_string($data[0])."',

'".mysql_escape_string($data[1])."',

'".mysql_escape_string($data[2])."',

'".mysql_escape_string($data[3])."',

'".mysql_escape_string($data[4])."',

'".mysql_escape_string($data[5])."',

'".mysql_escape_string($data[6])."',

'".mysql_escape_string($data[7])."',

'".mysql_escape_string($data[8])."',

'".mysql_escape_string($data[9])."',

'".mysql_escape_string($data[10])."',

'".mysql_escape_string($data[11])."',

'".mysql_escape_string($data[12])."',

'".mysql_escape_string($data[13])."',

'".mysql_escape_string($data[14])."',

'".mysql_escape_string($data[15])."',

'".mysql_escape_string($data[16])."',

'".mysql_escape_string($data[17])."',

'".mysql_escape_string($data[18])."',

'".mysql_escape_string($data[19])."',

'".mysql_escape_string($data[20])."',

'".mysql_escape_string($data[21])."',

'".mysql_escape_string($data[22])."',

'".mysql_escape_string($data[23])."',

'".mysql_escape_string($data[24])."',

'".mysql_escape_string($data[25])."',

'".mysql_escape_string($data[26])."',

'".mysql_escape_string($data[27])."',

'".mysql_escape_string($data[28])."',

'".mysql_escape_string($data[29])."',

'".mysql_escape_string($data[30])."',

'".mysql_escape_string($data[31])."',

'".mysql_escape_string($data[32])."',

'".mysql_escape_string($data[33])."',

'".mysql_escape_string($data[34])."',

'".mysql_escape_string($data[35])."',

'".mysql_escape_string($data[36])."',

'".mysql_escape_string($data[37])."',

'".mysql_escape_string($data[38])."',

'".mysql_escape_string($data[39])."',

'".mysql_escape_string($data[40])."',

'".mysql_escape_string($data[41])."',

'".mysql_escape_string($data[42])."',

'".mysql_escape_string($data[43])."',

'".mysql_escape_string($data[44])."',

'".mysql_escape_string($data[45])."')";

$result = mysql_query($sql) or die("Error: " . mysql_error() . "<br>");

$numRows++;

//echo "<br>";

}

fclose($handle);



// now look for duplicates

$sql_1 = "SELECT account_no,count(*) FROM tempTable GROUP BY account_no";

$result_1 = mysql_query($sql_1) or die("Error: " . mysql_error() . "<br>");

while(list($acct,$numcount) = mysql_fetch_row($result_1)) {

// if there is more than one delete all of them

if($numcount>1) {

//echo "acct: $acct, num: $numcount<br>";

$toBeRemoved+=$numcount;

$sql_delete = "DELETE FROM tempTable WHERE(account_no = '$acct')";

$result_delete = mysql_query($sql_delete) or die("Error: " . mysql_error() . "<br>");

}

else {

//echo "acct: $acct, num: $numcount<br>";

}

}



// now remove the duplicates who are already in the customer table

$sql_2 = "SELECT account_no FROM customerTable";

$result_2 = mysql_query($sql_2) or die("Error: " . mysql_error() . "<br>");

while(list($acct) = mysql_fetch_row($result_2)) {

//echo "acct: $acct, num: $numcount<br>";

$sql_delete = "DELETE FROM tempTable WHERE(account_no = '$acct')";

$result_delete = mysql_query($sql_delete) or die("Error: " . mysql_error() . "<br>");

}

// now send the user to the new page with more options
Header("Location: finish.php");

}





}

?>



<html>
<body>
<?php 

if(!empty($_GET['msg'])) {

$msg = $_GET['msg'];

echo "<strong>$msg</strong>";

}

?>
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>" enctype="multipart/form-data">
Upload CSV File: <input type="file" name="csvFile" size="30">
<input type="submit">
</form>
</body>
</html>
4

3 に答える 3

1

バックグラウンドジョブランナーを使用して、このようなことを行うことができます。私は最近これをたくさんやっています

https://github.com/seatgeek/djjob

http://seatgeek.com/blog/dev/djjob-a-php-port-of-delayed_job

お役に立てれば

于 2012-06-17T22:11:07.487 に答える
0

いくつかの db クエリのタイミングを計って、それらをまとめてバッチ処理してみてください。それらの1つがすべてを遅くしている可能性があります。

于 2012-06-17T23:03:08.680 に答える
0

1-tempTable.account_noとの両方customerTable.account_noが索引付けされていることを確認してください (おそらく、すでに主キーになっています)。ALTER TABLE temptable ENGINE=MEMORY;また、MySQLをメモリ内でのみ動作させることもできます(ディスクへの書き込みはありませんが、サーバーのシャットダウン時にテーブルの内容は失われます)。

2- CSV ファイルをテーブルにインポートするには:

ALTER TABLE tempTable DISABLE KEYS; -- otherwise, MySQL recomputes indexes after each line is inserted
LOAD DATA LOCAL INFILE 'yourfile.csv' INTO TABLE tempTable
FIELDS TERMINATED BY ',' ;
ALTER TABLE tempTable ENABLE KEYS; -- recompute all indexes in one go

入力ファイルの正確な形式に一致するLOAD DATAようにコマンドをカスタマイズする必要があります。

3- 重複を削除するには:

DELETE tempTable.*
FROM tempTable

-- match with the list of duplicates
LEFT JOIN (
    SELECT account_no
    FROM tempTable
    GROUP BY account_no
    COUNT(account_no) > 1
) AS duplicates
    ON duplicates.account_no = tempTable.account_no

-- match with records in customerTable
LEFT JOIN customerTable
    ON customerTable.account_no = tempTable.account_no

-- records with either duplicates, or with a match in customerTable
WHERE duplicates.account_no IS NOT NULL OR customerTable.account_no IS NOT NULL;
于 2012-06-18T23:29:24.220 に答える