• ベストアンサー

PHPを使ったスピード重視の集計について

以下のログがあります。 --- 日付   時分  A  B  C  カウント 2006/8/3 11:00 1  4  8  84 2006/7/4 17:04 3  5  4  47 2006/8/4 13:30 1  4  6  32 2006/3/3 15:15 5  1  8  8 2006/5/8 18:20 3  3  3  43 ・・・(以下、100万行位続く)・・・ --- このログを"時間"単位でA,B,C毎の"カウントを合計"したく、イメージとしては以下のテーブルを作りたいと思っています。(時間,A,B,Cの組み合わせでログに出て来なかったらテーブルに出力する必要無し。順番も特に問わない。) --- 日付   時間 A  B  C  カウント合計 2006/8/3 11  1  4  8  84323 2006/8/5 13  4  8  3  9793 ・・・・ --- 処理スピードを重視して、メモリ上で行う前提で以下の方式を考えました。 多段配列を使い、ログが出るたびに $count["2006/8/3"]["11"]["1"]["4"]["8"] = 7672 のような配列を作ります。もし、配列があるのならカウント部分を足し算します。 最後に配列全部をファイルに書き出すという方法です。 しかし、ログの量があまりにも多くやはり処理時間がかなりかかります。またプログラムも多段配列の表記にすると非常に見辛い状態です。何か別のアルゴリズムか手法により、スピード重視で処理する方法をご存知であればご教授ください。 前提がPHPを使わなければいけない&DB使えないという環境です。 よろしくお願いします。

  • PHP
  • 回答数4
  • ありがとう数3

質問者が選んだベストアンサー

  • ベストアンサー
回答No.3

# 2です。 ちょっと気になって簡単なスクリプトで試験してみました。 一旦配列に格納し、それを集計、というものをfor,while,foreachでやってみました。 結果としては、forとwhileの差はほんの数パーセントで、ほとんど変わらなかったです。 概ねのベンチ結果は平均で for 2.82に対して、while 2.79です。 foreachでは $i<$cnt のような判断式が無いせいかずっと速かった(1.55)です。 配列を展開しながら繰り返す場合はforeachがベストなようです。 > かなりの時間は1時間程です。 冗談ならないですね。この手はcronで夜中にでもやらないとしょうがないですね。 ひょっとしたらPHPではなくC++やシェルを使ってプログラミングし、外部スクリプト(exec関数)で呼び出す、と言う方が速い可能性も高いですね。 また、1時間ということでしたら、ディスクアクセスの時間は十分小さくなるので、ディスクを使ってメモリをうまく解放させる方が速いかもしれません。 では。

goroneko-begin
質問者

お礼

ループ文の種類によって速度が違うということは非常に驚きです。 他言語を使ってという事も考えられるのですが、利用制限がありPHPしか使うことができないという苦しい状況なのです。 Try&Errorでなんとか比較しながらやってみたいと思います。コメントありがとうございました。

その他の回答 (3)

回答No.4

# 2です。とりあえず下記URLに結果等を公開しました.

参考URL:
http://taketan.mydns.jp/xoops/modules/bwiki/index.php?PHP%2Ffor%A4%C8while%A4%C8foreach%A1%A2%BA%C7%C2%AE%A4%CF%A1%A9
goroneko-begin
質問者

お礼

すごい!! 大変参考になります。配列に入れてforeachでループさせたほうがかなり早いのですね。 大変参考になりました。ありがとうございます。

回答No.2

100万行ですか、凄いですね(笑。 かなり時間がかかる、のかなりはどれくらいですか? メモリ上で行なっていても、サーバの設定によってはメモリ上で行なわれなくなっている可能性もありますね。 php.iniの設定を変えてみて試験してみるのも一つの手かもしれません。 メモリで一杯になってしまっていた場合、ある程度のところでファイル書き出ししながらの方が速い可能性もあります。100万行ならば、桁数だけでも1メガな訳ですから、読込まれたデータだけでも相当なメモリを消費する可能性があります。1万行(あるいはもっと小さくても)ずつ処理した方が速いかも?しれません。 forよりはwhileの方が速い、と言う話もあります。 http://www.sound-uz.jp/php/test/first1.html 関数を使うより自作スクリプトの方が速い場合もあると思います。 サーバ環境、設定によって条件は左右されると思いますので、いくつか試してみて、最速の方法を見いだして下さい。出来れば、その結果を公開して下さい(笑。 参考まで。

goroneko-begin
質問者

お礼

コメントありがとうございます。 かなりの時間は1時間程です。早い感じもするのですが、もっと高速化を図りたいと思っています。 php.iniで使用メモリの設定もできるのですね。調べてみます。 forよりwhileの方が早い話、大変興味があります。話がそれますが、このような話好きなんですね。ちょっと研究して公開してみます。(笑

  • moon_night
  • ベストアンサー率32% (598/1831)
回答No.1

日付ごとや月ごとに予め計算されたデータを作っておいて、そこから読み出すと言うのはダメですか?

関連するQ&A

  • 集計方法について教えて下さい。PHP+MYSQL

    こんにちは、よろしくお願い致します。 データベースに下記のようなデータが入っています。 table_A cd name --------------- 1000001 aaa 1000002 bbb 1000003 ccc 1000004 ddd 1000005 eee 1000006 fff 1000007 ggg 1000008 hhh 1000009 iii 1000010 jjj table_B cd type point --------------- 1000001 A 100 1000001 B 50 1000001 C 30 1000004 C 20 1000005 B 70 1000009 A 10 1000009 C 40 table_Aと、table_Bから、下記table_Cの内容 table_C cd name count point_total ------------------------------ 1000001 aaa 3 180 1000002 bbb 0 0 1000003 ccc 0 0 1000004 ddd 1 20 1000005 eee 1 70 1000006 fff 0 0 1000007 ggg 0 0 1000008 hhh 0 0 1000009 iii 2 50 1000010 jjj 0 0 を得るには、どのようなSQLを書けば良いのでしょうか? table_Cのcount項目は、cdでマッチするtable_Bのtypeの種類をカウントしたもので table_Cのpoint_total項目は、cdでマッチするtable_Bのpointを合計した数値になります。 分かりにくい質問ですみませんがアドバイス頂けると嬉しいです。 具体的にどのような方法で実現できるか、教えて頂けると有難いです。 よろしくお願いいたします。

    • ベストアンサー
    • PHP
  • エクセルで日付データの比較/判定でカウント

    エクセルで日付データの比較/判定でカウント A1に 2006/2/22 A2に 2006/2/23 ---------- という日付データが入っている。 またc1~c4に c1:2006/2/24+時間  (例2006/2/24 07:18) c2:2006/2/23+時間 c3:2006/2/23+時間 c4:2006/2/22+時間 ---------- という時刻まで含む日付データが入っている。 (処理)A1とC列のデータの日付けが同じものは1つc4だけなのでカウントし1件とその横の B列(B1)にカウント件数を表示したい。 B1に書く式はどのようにすればよいか。よろしくお願いします。

  • [Access] 2つのテーブルを1つに集計したい

    アプリケーションのライセンス数のカウントをしています。 下記のように、既に購入済みアプリを場所毎にカウントしているテーブルAと、現在使用しているアプリ数を場所毎にカウントしているテーブルBがあります。 クエリ(でなくてもいいのですが)を使用して一番したの<最終的に欲しいクエリ>のような形にしたいのですが、どのようにしたらいいでしょうか。。 アドバイス宜しくお願いしますm(_ _)m <テーブルA> アプリ 場所 所持 ===================== A 東京 10 A 大阪 20 A 京都 8 B 東京 20 B 大阪 21 B 京都 18 C 東京 8 C 大阪 5 C 京都 10 <テーブルB> アプリ 場所 使用 ===================== A 東京 5 A 大阪 18 A 京都 7 B 東京 18 B 大阪 21 B 京都 15 C 東京 4 C 大阪 3 C 京都 9 <最終的に欲しいクエリ> アプリ 場所 所持 使用 ============================= A 東京 10 5 A 大阪 20 18 A 京都 8 7 B 東京 20 18 B 大阪 21 21 B 京都 18 15 C 東京 8 4 C 大阪 5 3 C 京都 10 9

  • Accessでテキストフィールドの集計

    ちょっと特殊な集計をしたいのですが テーブルはID(数値)と 記号(テキスト)の2つから構成されています。 ID   記号 1   A1,B2 2   A2 3   A1,A3 4   B1 5   A3,B2,C1 このようにデータが入っている場合 以下のように集計をするにはどうしたらよいでしょうか? 記号  カウント A1   2 A2   1 A3   2 B1   1 B2   2 C1   1

  • PHPの配列でわからないことがあるので教えてください。

    PHPの配列でわからないことがあるので教えてください。 例えば以下のような2つの配列$aと$bがあるとします。 $a[0]=a、$a[1]=b、$a[2]=c $b[0]=w、$b[1]=q、$b[2]=b、$b[3]=c これで、$a[1]と$b[2]の中身が同じであることを取得し、さらに$bの配列の添え字の2を返すようにしたいのですが、わかりません。 どのようにプログラムを書けばよいのでしょうか? よろしくお願いします。

    • ベストアンサー
    • PHP
  • エクセル :式の表現

    エクセルで日付データの比較/判定でカウント A1に 2006/2/22 A2に 2006/2/23 ---------- という日付データが入っている。 またc1~c4に C1:2006/2/24+時間  (例2006/2/24 07:18) C2:2006/2/23+時間 C3:2006/2/23+時間 C4:2006/2/22+時間 ---------- という時刻まで含む日付データが入っている。 (処理)A1とC列のデータの日付けが同じものは1つc4だけなのでカウントし1件とその横の B列(B1)にカウント件数を表示したい。 B1に書く式は=SUMPRODUCT((INT(C$1:C$4)=A1)*1) とすればいいのですが、このC$4という所を特にいくつまでと制限をしないでデータがあるうちは計算対象にする場合はどうすればいいですか。

  • PHPの配列について

    PHPの配列についての質問です。 以下のソースを // == ソース == function hoge( $foo ) { $arrs['a'] = 'A'. $foo; $arrs['b'] = 'B'. $foo; $arrs['c'] = 'C'. $foo; $arrs['d'] = 'D'. $foo; } hoge( '3' ); hoge( '9' ); // == /ソース == 実行すると print_rは // == print_r == Array (   [a] => A3   [b] => B3   [c] => C3   [d] => D3 ) Array (   [a] => A9   [b] => B9   [c] => C9   [d] => D9 ) // == /print_r == のようになります。 これを 関数を実行するごとに (0から IDのような 配列を組むようにする) 以下のようにするには どのようにすればよいでしょうか? // == print_r == Array (   [0] => Array     (       [a] => A3       [b] => B3       [c] => C3       [d] => D3     )   [1] => Array     (       [a] => A9       [b] => B9       [c] => C9       [d] => D9     ) ) // == /print_r == 使用目的は get_contentsしたものを正規表現で取り出し 配列にする処理に使おうと思っています。

    • ベストアンサー
    • PHP
  • SQLの集計

    「商品」テーブルについて商品コードごとにカウントしたいです。 ただ、「商品」テーブルには「商品コードA」と「商品コードB」がある。 「商品コードB」が空欄の場合は、「商品コードA」としてカウント。 「商品コードB」が空欄でない場合は、「商品コードB」としてカウントし、商品コードAの数に含めない。 ※「商品コードA」が空欄の場合はありえない。 これをSQL文でどう表現しますか? よろしくお願いします。

  • グループ集計と総合集計を行うには

    以下のようなテーブルが存在します。 A   B   C 1   1   3 1   2   4 2   3   3 2   2   3 ・・・・ 求めたい事は、 ・Cの総合計 ・A列におけるCの合計 ・A&B列におけるCの合計 です。3回SQLをまわせばいい事かもしれませんが、行数がすさまじく多いので1回もしくは2回のSQLで上記の結果が得られればいいなと思っています。 何かいい案がありましたらご教授いただきたくよろしくお願いします。

  • SQLで違うテーブルの集計結果を比較することは可能でしょうか?

    SQLで違うテーブルの集計結果を比較することは可能でしょうか? 例えばAテーブルがこんな感じです A1_ A2_ A3___ A4 ____A5 XX_ YY _5 __2010/8/13 _10:00:59 Bテーブルはこんな感じです。 B1_ B2_ B3___ B4 ____B5 XX_ YY_ 米 __2008/5/20_ 00:00:00 XX_ YY_ 味噌 _2009/8/22_ 01:02:33 XX_ YY_ 卵__ 2007/8/21_ 23:35:55 XX_ YY_ 醤油 _2010/7/16_ 15:30:35 XX_ YY_ 胡麻_ 2010/8/13_ 02:02:02 です。 見つけたい条件はBテーブルに指定した日付が含まれてる(例えば今日8/13だとか)レコードがあればそのXXとYYが何件あるかカウントをしてその値がAテーブルのA3の値と同一か調べたいのですがこういうことは出来ますでしょうか? SQL Server2005です

専門家に質問してみよう