(PHP&MySQL) hogeというDBがあるとします。ここにはユーザー名の userid というカラムとメールアドレスのemailというカラム、auto_incrementでつけた番号 number というカラムがあります。



又、ユーザーのメールアドレスを username.php というスクリプトで調べ email というカラムに入れています。

しかしユーザーのメールアドレスが良く変わり最新の情報をDBに登録するため毎週1回指定した時間に調べるようにさせたいのです。その際に大量にあるのでnumberの順に処理し、サーバーに負荷をかけないようnumberが1のレコードの処理が終わったら3秒おき、2のレコードの処理をという形にしたいです。又、200まで終わったら次は1時間後に201からといった感じの機能もつけたいと思っています。

以上を実現する簡単なソースをお願いします。

回答の条件
  • 1人5回まで
  • 登録:2006/04/28 22:39:23
  • 終了:2006/04/29 23:00:13

ベストアンサー

id:bonlife No.1

回答回数421ベストアンサー獲得回数752006/04/29 00:18:25

ポイント51pt

DBの操作関連は抜きにして、特定の時間ごとに処理をさせるためのサンプルスクリプトを書いてみました。

コマンドラインのPHPで以下のスクリプトを実行すると、1、2、3…と3秒置きに数字を出力し、200の部分で1時間待った後、201を出力します。

参考にしてみてください。

<?php
/*
  DBに接続
  SELECT MAX(number) FROM hoge;
  上記のようなSQLでレコード件数を取得し、変数$record_numberに格納
  以下では$record_numberを1000とする
*/ 
$record_number=1000;
for($i=1;$i<$record_number;$i++){
	if($i%200==0){
		/*
		  ここで更新処理
		  UPDATE文で1行更新
		  WHERE句で指定するnumberの値は$i
		  サンプルスクリプトでは単純に$iの値をecho
		  $iが200で割り切れる場合、待ち時間を1時間(3600秒)にする
		*/
		echo $i;
		sleep(3600);
	} else {
		/*
		  ここで更新処理 (上記と同じ)
		  $iが200で割り切れない場合、待ち時間は3秒にする
		*/
		echo $i;
		sleep(3);
	}
}
?>

DBの負荷が問題になるのは、同時にDBに大量のアクセスがある場合などが多いです。

サーバーに負荷がかかることを心配なさっているようですが、1件ずつUPDATEする程度でそれほど負荷が高くなることはないと思います。

CPU負荷、メモリ、両方とも特に問題ないと思いますので、一度開発環境などで処理を試してみて負荷を計測してみてはいかがでしょうか。

(すでに負荷が高いことが実証済みである場合は気になさらないでください。)

また、ユーザのメールアドレスの変更はどのようにして把握していますでしょうか。

ユーザがメールアドレスの変更を画面上で行えるようにし、随時UPDATEするようにすれば、一括処理の負荷を心配する必要もないと思います。

色々と事情があるとは思いますが、処理が集中しないようにフローを見直すことも重要だと思います。

参考になれば幸いです。

id:esecua

大変参考になるソースありがとうございます。

ごめんなさい、伝達ミスがありましたので以下の部分お願いします。

auto_incrementでつけてある数字ですが、レコードの消去などによってつながってないところがあります。 1 2 3 6 なような感じです。

後、毎週自動実行する機能も搭載したいと思っています。

以上お願いします。

2006/04/29 01:46:17

その他の回答(1件)

id:bonlife No.1

回答回数421ベストアンサー獲得回数752006/04/29 00:18:25ここでベストアンサー

ポイント51pt

DBの操作関連は抜きにして、特定の時間ごとに処理をさせるためのサンプルスクリプトを書いてみました。

コマンドラインのPHPで以下のスクリプトを実行すると、1、2、3…と3秒置きに数字を出力し、200の部分で1時間待った後、201を出力します。

参考にしてみてください。

<?php
/*
  DBに接続
  SELECT MAX(number) FROM hoge;
  上記のようなSQLでレコード件数を取得し、変数$record_numberに格納
  以下では$record_numberを1000とする
*/ 
$record_number=1000;
for($i=1;$i<$record_number;$i++){
	if($i%200==0){
		/*
		  ここで更新処理
		  UPDATE文で1行更新
		  WHERE句で指定するnumberの値は$i
		  サンプルスクリプトでは単純に$iの値をecho
		  $iが200で割り切れる場合、待ち時間を1時間(3600秒)にする
		*/
		echo $i;
		sleep(3600);
	} else {
		/*
		  ここで更新処理 (上記と同じ)
		  $iが200で割り切れない場合、待ち時間は3秒にする
		*/
		echo $i;
		sleep(3);
	}
}
?>

DBの負荷が問題になるのは、同時にDBに大量のアクセスがある場合などが多いです。

サーバーに負荷がかかることを心配なさっているようですが、1件ずつUPDATEする程度でそれほど負荷が高くなることはないと思います。

CPU負荷、メモリ、両方とも特に問題ないと思いますので、一度開発環境などで処理を試してみて負荷を計測してみてはいかがでしょうか。

(すでに負荷が高いことが実証済みである場合は気になさらないでください。)

また、ユーザのメールアドレスの変更はどのようにして把握していますでしょうか。

ユーザがメールアドレスの変更を画面上で行えるようにし、随時UPDATEするようにすれば、一括処理の負荷を心配する必要もないと思います。

色々と事情があるとは思いますが、処理が集中しないようにフローを見直すことも重要だと思います。

参考になれば幸いです。

id:esecua

大変参考になるソースありがとうございます。

ごめんなさい、伝達ミスがありましたので以下の部分お願いします。

auto_incrementでつけてある数字ですが、レコードの消去などによってつながってないところがあります。 1 2 3 6 なような感じです。

後、毎週自動実行する機能も搭載したいと思っています。

以上お願いします。

2006/04/29 01:46:17
id:bonlife No.2

回答回数421ベストアンサー獲得回数752006/04/29 11:31:09

ポイント19pt

どういう情報を元にDBを更新するのか、によってやり方は異なってくると思います。

番号が飛び飛びになっている場合でも、変更用の情報を持ったcsvファイルなどを用意しておき、そのリストを1行ずつ処理するようにすれば良いはずです。

まず、csvファイルの終わりに達するまで(feofでない間)、1行ずつ読み込んで(fgets)、内容を整形して(explodeあるいはpreg_split)SQLにし、処理を行います。

上記のサンプルでは$iをnumberとしていますが、$iを変更用リストの行番号(1行処理するごとに$iをカウントアップしておく)に置き換えるイメージです。

あらかじめ行数を取得しておくわけではないので、forではなくwhileでcsvファイルのポインタがfoefでない間処理を行います。

このやり方であれば、変更がない行に対しては処理を行いませんし、処理も早く終わると思います。

毎週自動実行する機能はPHP側で実装せずにcronを使って行うのが一般的です。

cronの使い方はこちらなどをご確認ください。

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません