プロが教えるわが家の防犯対策術!

初めまして。情報系の学部に通っている大学生です。
phpmyadminを使っています。

早速ですが、以下について質問です。

・データベースの1つのテーブル(3000行)から、データを取り出す
・それをもとに、(0,1など1ビットの)データを、4000行×72000列の配列に格納
これを実践するプログラムを作成したところ、作業完了に相当な時間を要します。
「php.ini」のタイムリミットを、デフォルトの60秒から18000秒(5時間)に変更しても足りないほどです。

そもそも、たかだか 1ビット×4000×72000 = 288,000,000ビット = 36MB(?)を扱うのに
何時間もかかるわけないですよね?

個人的には、配列の大きさ(4000行×72000列)や、データベースから取り出す行の数(3100行)が
比較的大きいのがミソかな、と感じています。
ちなみに、データベースにアクセスする回数が多いと動作も遅くなるのか、と思い、
データベースからデータを取り出す処理を、以下の2パターン試しました。
 1. 「SELECT * FROM xx 」 により、一度に3000行すべて取り出す
 2. 「SELECT * FROM xx WHERE yy = zz」により、取り出すデータを分ける。
   これをfor文で数十回繰り返す
しかし、どちらも同じような所要時間でした。

初心者のため、質問の仕方(情報量など)が不十分かもしれませんが、
お返事いただければ大変うれしいです。
必要ならソースコードも載せさせていただきます。

よろしくお願いいたします。

A 回答 (3件)

データベースで数万件のデータは普通なので3000程度であれば普通は問題ないですね


プログラムの途中でファイルに時間を記録するようにしてどの部分が時間がかかるか調べてみては

質問はPHPとMySQLのことでphpmyadminは今回の件とは関係ないですよね

この回答への補足

php504さん、
早速のご回答、ありがとうございます!

おっしゃる通り、phpmyadminでなくPHPとMySQLの問題ですね。
誤解を生じる表現を使ってしまい、反省しております。。。

早速「プログラムの途中でファイルに時間を記録する」方法を実践させていただきました。
ある箇所でtxtファイルに現在時刻を出力するよう設定したところ、
以下の部分が、1分間で平均2,3回しか処理できていないことが分かりました。

for(a=0; a<100; a++) {
 for(b=0; b<31; b++) {
  for(c=0; c<100; c++) {
   for(d=0; d<744; d++) {
    ・配列Hからデータを取得
    ・配列Hのデータ(zz)をもとにDBからデータを取得
     ("SELECT xx FROM yy WHERE zz")
    ・DBのデータをもとに、配列I、配列J、配列Kについて、
      データを取得または格納
   }
  }
  この時点でtxtファイルに現在時刻を出力
 }
}

txtファイルには本来、「現在時刻」が3100回保存されるはずですが、
実際はその3割弱の887回しか保存されていませんでした。保存された「現在時刻」から、
888回目でタイムアウト(php.iniで設定した18000秒=5時間)を迎えたことが分かります。

ちなみに、
配列Hは100*744(=74400)の2次元配列、
配列Iは100*31*24(=74400)の3次元配列、
配列J、Kはともに100*31(=3100)の2次元配列です。

配列やデータのサイズは大きいですが、これはどうしても避けられないのです。
配列やデータは必ずこの大きさ、という前提のもと、何とかサクッと処理できないでしょうか。

補足日時:2010/12/25 14:26
    • good
    • 0

PHPには、BIT型が無いので、1,0にしてみても、ソレはIntegerとなり、少なくとも8bitは消費するのではないでしょうか。



そして、PHPの配列はメモリ食います。
とりあえず、少なくとも4000行×72000列の値は常に「1」が含まれている配列を生成してみると、
<?php

echo "MEMORY0 : " . number_format(memory_get_usage()) . " byte(初期値)<br>";

$result = array();
for($i=0; $i<4000; $i++){
for($j=0; $j<72000; $j++){
$result[$i][$j] = 1;
}
}
echo "MEMORY1 : " . number_format(memory_get_usage()) . " byte(配列生成)<br>";

unset($result);
echo "MEMORY5 : " . number_format(memory_get_usage()) . " byte(配列解放)<br>";

?>

PHPのmemory_limitを512MBまであげても、途中でエラーでこけます。
この手の演算は、PHP(とか他のスクリプト言語)で扱うような事柄ではない気がします。

この回答への補足

hogehoge78さん、
ご回答ありがとうございます!

なるほど、PHPだと0,1でも8bit消費してしまうんですね。。。
早速、ご回答いただいたソースコードを「goo_answer.php」として
実行させていただいたところ、以下のエラーが返ってきました。

------------------------------------------------
MEMORY0 : 316,680 byte(初期値)

Fatal error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 262144 bytes) in C:\xampp\htdocs\goo_answer.php on line 8
------------------------------------------------

メモリ上限値を512MBに引き上げてもエラー…となると、
やはりPHPとしては限界なのでしょうか。。。

私自身はCとJavaを授業で学習したことがありますが、他の言語は初めてです。
Cや(アプレットなどでなく普通の)Javaは、スクリプト言語じゃないですよね?
配列処理の部分は、一度Cでやってみようかと思います。
他にオススメの言語があれば、是非お教えいただけないでしょうか。

補足日時:2010/12/25 14:44
    • good
    • 0

私も他の言語はあんまり触ってこなかった悪い子なので、オススメの、と言われるとなんとも言えないのですが、


とりあえず質問者さんがやったことのあるCとかJavaで試してみてはいかがでしょう。左記のものは、スクリプト言語ではないので、ソレよりは高速です。

PHPには、system関数とかexec関数といったものがあって、OSのコマンドを叩くことが出来ます。
http://jp2.php.net/manual/ja/function.exec.php
http://jp2.php.net/manual/ja/function.system.php

<?php
//execでCやJavaで書いたプログラムを叩く
//例はとりあえずWindowsのdirコマンド
exec('dir', $output);

//$outputには実行後に、標準出力が「\n」で区切られた配列で渡ってくる。
print_r($output);

?>

dirとしたところを、各言語のコマンドラインの実行で、やってみると。
そうすると、別の言語で処理を行って、結果を再度文字列で、ですがPHPで受け取れます。

当然それらのことが出来るサーバが必要になりますが。(レンタルサーバとかだと多分動かない。)
    • good
    • 0
この回答へのお礼

お返事が遅くなりました(^ ^;)
いただいたアドバイスをもとに試行錯誤を重ねた結果、
おかげさまで少しずつ改善しています。
ありがとうございました!!

お礼日時:2011/01/03 03:40

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!