ユーザ毎にアクセスログや操作ログなどを保存して出力するWEBシステムを作成しています。


基本的にデータの保存にはMySQLを使っているのですが、
1テーブルにログを蓄積していくと膨大になり、処理に影響が出る事を懸念しています。

自分で調べた解決策として

(A)ログは月ごとにファイルを作成し、アクセスがある毎に追加書き込みする。出力時は、日付を選択して対象ファイルを読み込み、一括出力。
(B)SQLiteを使い、ユーザ毎に専用のDBを作成してそこに書き込む
(C)MySQLのパーティショニングを使用する

現在はAで対処しているのですが、ログを検索したい時、DB構造ではないので困難です。
CはMySQLのバージョンに依存する為、出来れば使いたくないです。
Bの方法が良いとも思いましたが、はてなの過去ログを調べるとオススメ出来ないとの意見がありました。

そこで質問ですが、膨大化するデータを扱い、出力・検索する事を目的とした場合、
どのような方法を用いればよいのでしょうか?

こちらの環境はLAMPでPHP5.1.6とMySQL5.0.66を使っています。

回答の条件
  • 1人2回まで
  • 登録:
  • 終了:2008/10/08 20:33:12
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

回答3件)

id:standard_one No.1

回答回数252ベストアンサー獲得回数23

ポイント27pt

MySQLを使いテーブル末尾に _YYYYmm と年月情報を付加して、テーブルを月別に分ける処理を作ったことがあります。

個人的には悪くない処理方法だと思っています。

id:k27w

MySQLのテーブルを分けるという事は考えていませんでした。

ログ専用のデータベースを作り、そこにおっしゃる方法でログ専用のテーブルを作成するのもありですね。

参考にさせていただきます。

2008/10/08 10:53:52
id:pahoo No.2

回答回数5960ベストアンサー獲得回数633

ポイント27pt

一般論として、アクセスログや操作ログは、更新ではなく追加のみのデータです。また、一般ユーザーに利用させる性質のものでもないので、トランザクションが増えたり応答速度(検索性能)が要求されるものでもありません。さらに、アクセスログや操作ログをユーザー毎に分離することによって、当該ユーザーの行動が明らかになりますので、個人情報に準じた扱いが求められます(「経済産業分野を対象とする個人情報保護ガイドライン等について」参照)。

よって、MySQLやSQLiteといったセキュリティ面では強くないDBMSを適用するより、セキュリティ対策を施したテキストファイルとして格納することが検討候補となります。

機能的にはシングルスレッド処理になるはずなので、検索条件に適したインデックスファイルを作っておけば、単純テキスト検索でもDBMSに匹敵する速度を実現することが出来ます。


いずれにしても、機能要件として以下を整理すべきかと存じます。

  1. 対象ユーザー数
  2. 対象ログの件数
  3. 対象ログの期間
  4. 検索条件
  5. 検索頻度
  6. 要求される応答時間
id:k27w

回答されているのは、私が質問で挙げた「A」の方法に近いと思います。


ただ、「検索条件に適したインデックスファイル」という説明が少しわかりません。

私の場合、


log/ユーザID/(日付).log


というような構造で、ログを保存しています。

ファイル内はカンマ区切りでアクセス者のホスト名やブラウザ情報などを保存しています。


pahooさんのおっしゃる「インデックスファイル」というのは、検索対象とする要素(ホスト名やブラウザ情報)なども別ファイルにすると言う事でしょうか?


ちなみに「テキスト検索」がそこまで早いという実感がないです。1度ファイルをすべて読み込んで、それぞれ検索対象(カンマ区切り毎)に配列に代入しているからなのかも知れませんが。

2008/10/08 11:02:52
id:pahoo No.3

回答回数5960ベストアンサー獲得回数633

ポイント26pt

#2のコメント:

ただ、「検索条件に適したインデックスファイル」という説明が少しわかりません。

たとえば、検索条件がユーザーIDと年月日だけなら、"log/ユーザID/(日付).log" というファイル構造それ自体がインデックスの役割を果たすので、インデックスファイルは不要と考えます。

もし、ユーザーIDや年月日は問わずに、ブラウザの種類だけを検索条件にするということでしたら、".log" ファイルとは別に、どのブラウザのアクセスログはどの ".log" ファイルにあるかを示す(インデックスする)ファイルが必要だということです。

インデックスファイルも追加するのみですので、cronを仕掛けてCPU付加が少ない時間帯に追加更新すればよいでしょう。


ちなみに「テキスト検索」がそこまで早いという実感がないです。1度ファイルをすべて読み込んで、それぞれ検索対象(カンマ区切り毎)に配列に代入しているからなのかも知れませんが。

私が想定している処理フローは、".log"の頭から末尾に向かって検索を行い、ヒットした情報のみを変数に代入していくものです。今回は戻り検索(途中で末尾から頭に戻る)は無いはずなので、それほど遅くなるとは思えません。


ただ、dev_zer0 さんがコメントしているように、また、私が#2ご回答したように、データ要件が分からないと適切なアドバイスが出来ませんし、そもそも設計ができないはずです。

業務用ならもちろんのこと、たとえ私的なシステムであっても、アクセスログ+操作ログという準個人情報を扱う仕組みですから、きちんとした設計をすべきかと存じます。バッファオーバーフローを起こしてログが外部流出するようなことになったら、ただでは済まされません。

id:k27w

もし、ユーザーIDや年月日は問わずに、ブラウザの種類だけを検索条件にするということでしたら、".log" ファイルとは別に、どのブラウザのアクセスログはどの ".log" ファイルにあるかを示す(インデックスする)ファイルが必要だということです。


つまり、私がカンマ区切りで1ファイルに記述している内容を、別ファイルにする事で、”検索条件に適したインデックスファイル”が出来るというわけですね。


ファイル数が増えますが、その方が汎用性が高いのなら、ひとつの手として考えます。


ただ、dev_zer0 さんがコメントしているように、また、私が#2ご回答したように、データ要件が分からないと適切なアドバイスが出来ませんし、そもそも設計ができないはずです。


コメントにも記述しましたが、ある程度の想定は出来ています。しかしながら、質問しているのは皆様の”経験則を教えて欲しい”わけですから、設計の考え方と共に「○○万件のデータを扱った場合、××になったので、インデックスファイルに分けました」というようなお話しが聞きたかったです。(質問の仕方が悪いかも知れませんが…)


質問に「膨大化したデータを扱い~」としているわけですから、回答者様毎の”膨大化”と捉える範囲があるのではないでしょうか。


過去の質問からこちらで「○件を対象にしています」としても、「それなら1テーブルに入れるだけでよい」という回答だけのものがあり、先の事を想定出来ないので、あえて条件を指定しませんでした。

2008/10/08 17:47:56
  • id:chuken_kenkou
    >1テーブルにログを蓄積していくと膨大になり、処理に影響が出る事を懸念

    「過去何日分を溜め込むのか」、「同時に接続する最大ユーザ数はどのくらいなのか」、「一つのトランザクションでどの程度、SQLを発行するのか」といった情報はないのですか?

    >(C)MySQLのパーティショニングを使用する

    ログを取るためだけに、パーティショニングが必要なほど高負荷になるようには思えませんが?
  • id:k27w
    >「過去何日分を溜め込むのか」、「同時に接続する最大ユーザ数はどのくらいなのか」、「一つのトランザクションでどの程度、SQLを発行するのか」といった情報はないのですか?

    ありません。構造時からある程度想定して開発すると思いますが、実際には「運営してみないとわからない」のではないでしょうか。

    ですので、最低限必要な範囲と「ここまで考えているならこうするべき」という回答が欲しいのです。

    >ログを取るためだけに、パーティショニングが必要なほど高負荷になるようには思えませんが?

    同上です。パーティショニングはあくまで「考えたこと」であって、「やりたいこと」ではありません。
    出来れば”思えない”と思った理由を書いていただければ良かったのですが・・・
  • id:dev_zer0
    え?
    > 「過去何日分を溜め込むのか」
    これは決めておかないとマズイと思いますよ。
     
    あと、一日でどれぐらいのアクセスがあるかを想定しておかないと
    ディスク容量の見積もりができないはずです
     
    「運営してみないとわからない」は確かに分からないかもしれませんが、
    ざっくりといいので見積もり容量×安全率を取りあえず出しておいて
    稼動して数日ぐらい様子を見てこのままでいいのか、
    ディスクを増設する必要があるのかという見極めは必要だと思います。
     
    空き容量が足りなくてログが出せませんという事態は避けるべきだと思います
    # 意外とログは容量を食います
  • id:k27w
    dev_zer0さん

    おっしゃるような要件は想定していますよ。

    ただ、こちらが質問した時にすべての要件をだして「この条件の場合は~」と尋ねるよりも、皆様のご経験から来るノウハウをお尋ねしたかったので、質問したのです。

    この件に関しては、「○○件のログの場合、××した方が良い」という回答が得られると思ったのですが…どうやら違うみたいですね。
  • id:dev_zer0
    > 「○○件のログの場合、××した方が良い」という回答が得られると思った
    はい、違います。
    そのログが参照される頻度、1レコードのログのサイズ、レスポンスタイム
    コストやその他の色々な条件により全然違う回答になります。
     
    参照回数が多く、比較的ログのサイズが小さく、レスポンスタイムがシビアな要件でしたら
    ログをDBに突っ込んでおいたほうが良いでしょう。
    参照回数が少なく、レスポンスタイムは気にしないようでしたらテキストファイルで管理しておいて
    スクリプトか何かで加工すれば良いでしょう。
     
    一日で大量のログが出力される場合、OSによっては1つのログファイルで
    ファイルサイズの上限を超える可能性もあるので
    ローテートするか、そのタイミングをどうするかも考える必要があるかもしれません。
     
    コストがかかりますが、ログサーバを立ててしまえは
    webサーバに負荷をかけずにログ検索を容易に行えます。

    ということで、あなたの提示した条件では私の経験上何も回答できません。
    ご理解いただけたでしょうか?
  • id:k27w
    回答出来なければ答えなければ良いのではないでしょうか?無理に時間を割いて長文を書いて私の質問を正したいのですか?

    とはいえ、上記に書いていただいた指摘は勉強になりました。
  • id:pahoo
    k27w さんが求めておられるのはDB設計方式に関わるノウハウだと思うのですが、この場で仕事のノウハウを開示するわけにもいきません。そこで、我が家が運営しているサイト「ぱふぅ家のホームページ」(http://www.pahoo.org/)を例に説明します。
    このサイトのアクセス状況は次の通りです。

    ●1日あたり平均
    ・ユニークユーザー 約3,000人
    ・アクセスログ 約10Mbyte

    ●1月あたり平均
    ・ユニークユーザー 約25,000人
    ・アクセスログ 約300Mbyte

    ユニークユーザーには重複があるため、1月あたりにするとだいぶ少なくなります。

    アクセスログは Apache の生ログです。もちろん操作履歴は取得できないため、アクセスログと同じだけの容量があると仮定して、k27w さんの方式で1月あたりに発生するファイル量を計算してみます。アクセス数はそれほど変動しないサイトなので、安全率は20%にしました。

    ●毎月必要な容量
    ・ディレクトリ数 30,000
    ・ファイル数 108,000
    ・ログファイル容量 720Mbyte

    1年間で計算すると、ファイル容量だけで8.6Gbyteになりますから、そもそもウチで借りているレンタルサーバの容量を大幅にオーバーします。
    かりに、これをDBMSにできたとしても、相当のコストがかかります。また、ファイル単位で格納するとしても、小さなファイルが大量にできるので、ストレージの方式が問題になってきます。さらに、準個人情報を扱うレベルのセキュリティ対策も施さなければなりません。(インフラ設計方式及びコスト見積については業務ノウハウの範疇になるのでご勘弁を)
    それでも導入すべき機能なのだとすると、いかにコストを抑えて導入できるかを検討する必要が出てきます。

    費用を度外視した方式検討は時間の無駄であると、私は考えます。
    そして、残念ながら、こうした機能を“常識的な”金額で導入できる仕組みを、私は知りません。
    したがって、ウチのサイトより小さな規模のものであることを示していただかないと、私は適切なお答えをすることができないのです。

    ちなみに、ウチのサイトの場合、コンテンツ毎の関心度を知りたいので、ユーザー情報を捨てて、ユニークユーザー数とコンテンツ毎・日時毎のアクセス回数を集計しています。
    手順としては、サーバ負荷を軽減するため、1日1回だけcronを走らせ、アクセスログのサマリーをMySQLに記録するようにしています。年間に消費するDB容量は約80Kbyteです。
    集計結果は以下のURLで公開しています。
    http://www.pahoo.org/entrance/ranking.shtm
    レンタルサーバからのレポートでは、この処理に関わるCPU負荷は無視できるほど小さいものです。

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

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

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

回答リクエストを送信したユーザーはいません