<< セッションのタイムアウトについて 質問一覧 携帯から画像をアップロードするには >>
  • キーワードが設定されていません

  • 500P
効率的なソートプログラムについて

業務用のプログラムを組んでいるのですが、プログラム経験が浅い事から、
作成したプログラムがやたら処理が重くなってしまい効率的なプログラムをお聞きしたくて質問させて頂きます。
phpとmysqlで組んでいまして
内容としましては
 投稿ID
 時間
 メーカーID(1~50程度)
 機種ID(メーカーごとに1~80程度)
 機種名(個別の機種名で名前は他とかぶりません。保存していますがメーカーIDと機種IDごとの(50×80程度の個別の機種名を毎回保存しなおしてます)
 地域(大まかに8地域程度に分かれています)
 台数


   の6つのデータを含むデータベースのデータを引っ張り出してきて、
機種名と地域が一致する場合 台数を合計、時間を新しい物を適用(メーカーIDと機種名、地域も一応再保存) という合体した配列を保存して時間が新しい順に表示してます。

  1. sql = select * from DB名 order by 時間
  2. として600ぐらい入っている列を
  3.  
  4.  
  5.  
  6. $y = 0;
  7. ($limeには配列は行ってます)
  8. while($row=mysql_fetch_array($line)) {
  9.  
  10. for($x=1;$x <= $y;$x++){
  11.  
  12. // 機種名が同じで
  13.   if($rowh[2][$x] == $row[2]){
  14.  
  15. // 地域も一緒なら
  16.     if($rowh[3][$x] == $row[3]){
  17. // 件数追加
  18.   $rowh[30][$x] = $rowh[30][$x] + 1;
  19.  
  20. // 台数を他のものと合計
  21.   $rowh[6][$x] =   $rowh[6][$x] + $row[6];
  22.  
  23. // 時刻が新しい物があればそちらの時刻を保存
  24.       if($rowh[13][$x] < $row[13]){
  25.       $rowh[13][$x] = $row[13];
  26.       }
  27. // 機種と地域が一緒ですよというフラグ
  28.   $check = 1;
  29.     }
  30.   }
  31. }
  32.  
  33. // 機種と地域が一緒じゃなければ新しい列として保存していく
  34. if($check != 1){
  35. $y = $y + 1;
  36. $rowh[2][$y] = $row[2];
  37. $rowh[0][$y] = $row[0];
  38. $rowh[1][$y] = $row[1];
  39. $rowh[3][$y] = $row[3];
  40. $rowh[4][$y] = $row[4];
  41. $rowh[5][$y] = $row[5];
  42. $rowh[6][$y] = $row[6];
  43. $rowh[9][$y] = $row[9];
  44. $rowh[10][$y] = $row[10];
  45. $rowh[12][$y] = $row[12];
  46. $rowh[13][$y] = $row[13];
  47. $rowh[16][$y] = $row[16];
  48. $rowh[17][$y] = $row[17];
  49. $rowh[19][$y] = $row[19];
  50. // rowh[2][$t]の機種が何件出ているかをrowh[30]に保存していく
  51. $rowh[30][$y] = 1;
  52. // (すいません色々他のデータも保存しちゃってます。一応16がメーカーID17が機種ID。途中で出てきてますが2が機種名、地域が3、時刻が13になってます。)
  53.  
  54. }
  55. $check = 0;
  56.  
  57.  
  58. // whileのデータベースの回転 ここまで 
  59.  
  60. }

このようなプログラムを組んでいるのですがあまり効率的なプログラムの組み方を知らない故に無駄に600×600回ぐらい回転しちゃってます。
今後長い目ではデータ数が2000近くまで行く予定もあるため現時点で重く感じているので厳しいと思い質問させて頂きました。

ポイントとしましては
・メーカーID、機種IDごとに個別の機種名が特定されますので sqlで引っ張る段階でメーカーID、機種ID、地域でソートしたデータにしておけば隣と比べるだけで済む?(その代わり再度時間順に並べなおす必要がある。)
・時間順で引っ張ってきてから機種名同じものを集めるのと機種名をできるだけ寄せておいて比較量を減らしてから時間順に直すのだとどちらの方が早くなるか。
・またif文内で機種名(日本語で文字数長い)が同じ場合としてますがメーカIDと機種ID(両方とも数字)が同じ場合などとすると比較する文字列が長いのと2回比較するのではどちらが早くなるでしょうか?
・もしくは他に抜本的に効率的にできる方法や関数などがあったりしますか?基本的なforループで頑張ってるので^^;

少しでもタスクを減らして早く表示される物にしたいと思うのでアドバイス、ご意見をお願いいたします。

この質問への意見の募集は締め切られ、ポイントは既に配分されました。
意見を投稿することはできますが、ポイントを受け取ることはできません。

Q効率的なソートプログラムについて kurann  [11月21日 19時01分] 
┣満開Re:効率的なソートプログラムについて kaitau  [11月21日 19時14分] 
┃┗Re:Re:効率的なソートプログラムについて kurann  [11月22日 19時27分] 
┃  ┗Re:Re:Re:効率的なソートプログラムについて kaitau  [11月22日 20時39分] 
┗満開Re:効率的なソートプログラムについて dala00  [11月22日 01時38分] 
  ┗Re:Re:効率的なソートプログラムについて kurann  [11月22日 19時37分] 

コメント一覧

並び替え( ツリー順 / 投稿順[降順] / 投稿順[昇順]

Re:効率的なソートプログラムについて

ロジックでがんばるのも結構ですが、DB使えるならそちらに任せたほうが得策ですよ。

select 機種名,地域,sum(台数),max(時間)
from テーブル
group by 機種名,地域
order by 4 desc,3 desc

みたいな感じで。
もっと疑問を解決したい場合は、SQLについて扱ってる掲示板かメーリングリストに行って、
そっちで(必要な部分のテーブル定義を一部公開して)質問されるといいでしょう。

Re:Re:効率的なソートプログラムについて

ありがとうございます。
まさにこれでした。
上記記載のsumやmaxのおかげで必要なプログラムを大きく代用できました。

Re:Re:Re:効率的なソートプログラムについて

ちょっとだけ補足を。

もしこの手のsqlが初めてなら、
group by 句を用いているからこそ、
機種地域ごとのsumとmaxが有効に働いていることも留意してくださいね。

Re:効率的なソートプログラムについて

上記の書き込みに追記になりますが、
SQLは、条件を設定してデータを受け取ることが出来ます。
phpで直に書くよりMYSQLに任せてしまった方が早いので、
そちらを利用しましょう。

条件はWHEREで指定します。

SELECT SUM(*) AS daisu_count, * FROM テーブル名 
WHERE 機種名='$kishumei' AND 地域='$chiiki'
ORDER BY 時刻

これで条件に合ったものだけが配列に入ります。
あと、後々テーブルの構造を変更した時にも問題がないよう、
mysql_fetch_arrayではなくmysql_fetch_assocの方がよいかもしれません。
$row['id'] とかでアクセスできますので。

あと、再保存は本当に必要なければ無駄なので止めたほうがよいと思います。

構文については色々と調べるともっと色々なことが出来ますので
是非調べてみて下さい。

Re:Re:効率的なソートプログラムについて

丁寧な説明でありがとうございました。
mysql_fetch_assocや再保存についても参考にさせて頂きます。
回転部分の効率は非常によくなったのですが、もう一つ重い要因がわかりまして、実際はurl_exists()の関数を利用していて、全機種ごとに外部サイトのファイルが存在しているかどうかのチェックをしていて存在すればリンクを張っていたため、この関数がもう一つ重い原因だったようです。
関数自体が重くなるのは変えれなさそうな気がするので、機種ごとにファイルがあるかどうかを記載したデータを作成しようかと模索しています。
丁寧にご説明頂きありがとうございました。
セッションのタイムアウトについて 質問一覧 携帯から画像をアップロードするには