MySQLを使うのか、ファイルを使うのか?データ記録の負荷削減方法

このQ&Aのポイント
  • 頻繁に書き換わるデータの記録について、MySQLを使用しているテーブルにIPとタイムスタンプを記録し、古いIPを削除するプログラムがある。
  • しかし、数万、数十万のIPが増えると、MySQLの負荷が増える可能性があるため、ファイルを使用して記録する方法を検討している。
  • IPの1文字目、2文字目などからディレクトリを分け、ファイル数を制限することで負荷を軽減できるかを検討している。MySQLとファイルのどちらが処理速度が速いかを知りたい。
回答を見る
  • ベストアンサー

頻繁に書き換わるデータの記録について

CREATE TABLE `ip` ( `ip` varchar(100) COLLATE utf8_unicode_ci NOT NULL, `date` datetime NOT NULL, PRIMARY KEY (`ip`), KEY `date` (`date`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci このようなMySQLのテーブルがあり、サイトに訪問者がアクセスしてきたら SELECT ip FROM ip WHERE ip = "{訪問者のIP}" のようにしてIPが記録されているかを確認し、もし記録されていなければ INSERT INTO ip VALUE ('{訪問者のIP}','{現在のタイムスタンプ}') のようにしてIPとタイムスタンプを記録し、その上で DELETE FROM ip WHERE date < '{7日前のタイムスタンプ}' のようにして古いIPを消す、みたいなプログラムがあります。 このようなプログラムで記録するIPが数万、数十万と増えてきたとき、 負荷削減などを考えるとMySQLを使わずに、 INSERTの代わりにファイル名がIP、内容が空のファイルを生成し、 SELECTの代わりにファイルが存在するかをチェックし、 DELETEの代わりにファイル生成時間が7日前以前のファイルを削除する、 というようなプログラムにしたほうがいいのかと疑問を抱えています。 IPの1文字目、2文字目などから適宜ディレクトリ分けし、 1ディレクトリ内のファイル数が多くならないように調整するようにと考えています。 MySQLを使うのと使わないのとで、 一般的にはどちらのほうが高速に処理できますか? よろしくお願い致します。

  • MySQL
  • 回答数3
  • ありがとう数9

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

  • ベストアンサー
  • notnot
  • ベストアンサー率47% (4848/10261)
回答No.1

MySQL等のDBMSの方が高速です。

php_noob
質問者

お礼

理由も欲しかったです。

その他の回答 (2)

  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.3

たんにログを冗長にとりつづけるならロガーで十分ですが 集計を考えるならファイルでの管理は考えられないですね 頻度が高い場合はHEAPで処理するとか、デバイスをSSDにするとか いろいろスピードアップはできますが極度に頻度が高くなると 実はMySQL自体がボトルネックになるケースもあります NoSQLなど別の切り口もありますが、HandlerSocketなどMySQLの拡張で 対応することもできるようです。 この辺のオーバーヘッドが気になるころには実は個人であれこれ 考えるレベルではなくなっている状況なんですけどね

php_noob
質問者

補足

集計における利便性ではなく、どちらのほうが高速かについて質問してます。 とはいえ、勉強になりました。 ご回答ありがとうございました。

  • BellBell
  • ベストアンサー率54% (327/598)
回答No.2

『このようなプログラムで記録するIPが数万、数十万と増えてきたとき』 実際に、このような状況になってから心配しましょう。 ま、そういう1日数十万アクセスのあるサイトの運用経験はありますが、そのときはIP重複チェックなどせずにバンバンとデータをインサートしていって、cronで短時間毎(10分毎など)に過去データや不要なデータを削除して、集計して統計データに変換しながら別のDBに登録をして…と、時間の掛かる処理は裏で動かすような工夫を盛り込んでましたけどね。 求められる機能がリアルタイム性を求められるのかどうかによって、どういう工夫を盛り込めばいいのかなどが異なりますが。 ま、サーバの負荷はあまり気にしなくてもいいんじゃないですかね。 アホな高負荷システムを作ったというならともかく、大量アクセスが原因の高負荷なら、その大量アクセスに耐えられるサーバに乗り換えりゃいいわけで。 アクセス数が多い=稼げる(?)サイトなんだから、高機能サーバ、高機能プランに乗り換えは当たり前と。 (あくまで、アホな高負荷システムではないという大前提) ま、ファイルで分けるとするとファイル日付を変更するためにタイムスタンプ変更。 トランザクションが効かせる事のできないファイルシステムを利用するわけなので、タイミングのエラーが発生するかも知れないのでそのエラー対策。 同時に同一ファイルにアクセスするプロセスが複数あった場合の為にファイルロック。 ファイル数が多くなれば、効率が悪くなるからとIPの1文字目、2文字目などから適宜ディレクトリ分け、その場合にディレクトリの存在非存在チェック。 どうやら、アホな高負荷システム(=他に簡単確実、低負荷な方法があるのに、わざわざ無意味に難しく高負荷な方法を選んだシステム)が出来上がりそうな予感です。

php_noob
質問者

お礼

「どちらのほうがサーバーに負荷がかからないか」に対して 「負荷を気にする必要のないくらい良いサーバーを使え」では何の解決にもなりません。 質問に対して回答する気がないのなら投稿しないでください。 読む時間がもったいないです。

php_noob
質問者

補足

> 実際に、このような状況になってから心配しましょう。 すでにこのような状況になっているから質問してます

関連するQ&A

  • mysqlコマンドとPHPで同じSQLの結果が違う

    MySQL 5.5で、mysqlコマンドからSQLを流したときと、PHPから同じSQLを発行したときで結果が違うのです。 どうも日付のパースが関係しているようで、「2014-08-19」と書くとどちらも同じ結果になるのに、 「2014-8-19」と書くとPHPでは1行も返ってこなくなります。 再現例: ================== CREATE TABLE t (day date NOT NULL) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; INSERT INTO t (day) VALUES ('2014-08-19'); SELECT * FROM t WHERE day = '2014-8-19'; +------------+ | day | +------------+ | 2014-08-19 | +------------+ 1 row in set (0.00 sec) ↑同じSELECTをPHPから発行すると1行も返ってこない。 ================== mysqldとmysqlは5.5.30。 phpinfo()のmysqlのセクションでは Client API version 5.5.30 と出ています。 show variablesで見るとdate_formatはどちらも%Y-%m-%dになっています。 他にどこを確認すればいいでしょうか?

  • SQLへファイルを格納

    PHP+MySQL(接続にはDB.phpを利用)を利用してフォームからファイルを アップしてそれをDBに格納するプログラムを組んでいるのですが データベースの構造は CREATE TABLE `test` ( `id` int(11) NOT NULL auto_increment, `filedata` longblob, `kaku` text collate utf8_unicode_ci NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=4 ; 下記がそのプログラムの処理部分です。 $data = file_get_contents($_FILES['upfile']['tmp_name']); $sql ="INSERT INTO test(filedata,kaku) VALUES('$data','$kaku')"; $DbObj->DBSQL($sql); ・$DbObj DB.phpを利用してのデータベース接続オブジェクト(クラス)で クラスの中身は商用のWebアプリの開発用のため掲示できませんが この処理以外は正常に動いています。 $sql ="INSERT INTO test(filedata,kaku) VALUES('11','$kaku')"; では正常動作確認しています。 ・$kaku ファイルの拡張子を格納している(拡張子はファイルを取りだ時に利用) 主キーはauto_incrementを利用しているのでINSERT文で設定の必要なし。 って状況で実行をすると DB Error: syntax error とエラーをはき処理できません。 どのようにしたらデータベースに格納できのでしょうか?

    • ベストアンサー
    • PHP
  • phpMyAdminの接続照合順序が勝手に変わる?

    質問があります。 phpMyAdminの接続照合順序が自分でphpMyAdminから 変更した以外で変わることってありますか? 以下の環境で、あるデータベース(ex_db)がありまして そのデータベースとそれに含まれるテーブルなども全て utf8_unicode_ciという接続照合順序になっていました。 ですが、今日また見てみるとデータベースはutf8_unicode_ciの ままですが、それ以下のテーブルなどは全てeucjpms_japanese_ci に変わっていて、文字化けが発生していました。 一応サイトではちゃんと表示されているのですが、接続照合順序を utf8_unicode_ciに変更しても文字化けは直りませんでした。 ちなみにphpファイルは全てutf8で記述されています。 今日急に変わっていたので困っています。 ご回答をよろしくお願いします。 phpMyAdmin: 2.11.9.2 MySQL クライアントのバージョン: 5.0.33 サーバ: Localhost via UNIX socket MySQL の文字セット: UTF-8 Unicode (utf8) 接続照合順序:utf8_unicode_ci

  • ACCESSとphpmyadminの文字関係に関して

    ACCESSからODBC経由でmysql へデータをインポートしました。 結果、phpmyadminで参照した時に、案の定文字化けしていました。 MySQLの文字セットは UTF_8 Unicode(utf8) MySQLの接続照合順序 utf8_general_ci で、テーブル上の各項目の照合順序は utf8_general_ci となっています。 config ファイル等を変更しなければならないかと思いますが、どのように変更すれば良いか教えて頂きたいと思います。 あるいは、そもそもACCESSからインポートする時に何か設定をしなければならない??? よろしくお願いします。

    • ベストアンサー
    • MySQL
  • 検索の際の濁点区別のかき方

    環境:mysql と php でプログラム作ってます。 実施したいこと: mysqlのカラム設定上は utf8_unicode_ci に設定してますが、これだと検索した際 濁点もヒットしてしまうので、 検索結果時に濁点判定を入れたいと考え 以下のプログラムを書いてます。 $sql="select * from テーブル名 where name like '%".$keyword."%' or tel like '%".$keyword."%' collate utf8_bin"; $sql .= "limit " .$page*10 . ", 10"; $datas = mysql_query($sql, $db); while($row=mysql_fetch_array($datas)){ $name = $row["name"]; しかし、実行すると $name = $row["name"]; で記述している箇所でエラーが出てしまいます。 エラーは、 mysql_fetch_array() expects parameter 1 to be resource, boolean given in となっており、 DBからデータを引っ張れていないと思われます。 検索時だけ、collate utf8_binを記述するのは間違っていたのでしょうか。。 アドバイスよろしくお願いいたします。

    • 締切済み
    • PHP
  • tableをつくれない

    CREATE TABLE `db31_dev`.`db31_dev` ( `keyword_id` SERIAL NOT NULL , `bc_guid` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , `bc_wbs` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , `keyword_h1_url` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , `keyword_wording_in_bc` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , `keywords` VARCHAR( 511 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , `description` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , `last_modified` DATETIME NOT NULL , `changefreq` VARCHAR( 15 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , `pri` INT( 5 ) NOT NULL , `noLocalNavi` BOOLEAN NOT NULL , PRIMARY KEY ( `keyword_id` ) , UNIQUE ( `bc_guid` , `bc_wbs` , `keyword_h1_url` , `keywords` , `description` ) ) ENGINE = InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci; とphpmyadminでうったら(正確にはテキストボックスに入力) priの部分がエラーと言われて、 MySQLのメッセージ: ドキュメント #1071 - Specified key was too long; max key length is 767 bytes だそうです。 どうすればいいのでしょうか? よろしくお願い申し上げます。

    • ベストアンサー
    • MySQL
  • MySQLでinsertできない原因は?

     PHPとMySQLでちょっとした掲示板とメールフォームを作って使ってもらってます。  メールフォームを使ったメッセージをMySQLのデータベースに記録するように作ってるんですが、たまにメッセージだけが記録されてないことがあります。名前とかメールアドレスとかのカラムは記録されてるんですが。  フォームはUTF8で表示されるようにしていて、特に文字コードの変換をすることなくそのままinsertしてるので、最初は文字コードの関係かなと思ったんですが、Androidだったり、iOSだったりするし、JISでもUTFでもなさそうなのでで、いまいち特定できず。  そもそも、文字コードが合わなくても、文字化けした状態で記録されますよね?  こういった場合、何が原因と考えられるでしょうか?  ちなみにMySQLの方は「utf8_general_ci」で設定しています。

    • ベストアンサー
    • MySQL
  • mysqlのインデックスについて質問です。

    mysqlのインデックスについて質問です。 http://archiva.jp/web/server-side/sql_02.html に、 『mysqlでは1つのクエリ実行で、1つのテーブルにつき1つのインデックスしか使用できない』 とあります。 よく以下のようなテーブル定義を見かけますが、 CREATE TABLE IF NOT EXISTS `data` ( `id` int(10) NOT NULL default '0', `user_id` int(10) NOT NULL default '0', `file_id` int(10) NOT NULL default '0', `name` text collate utf8_unicode_ci NOT NULL default '', PRIMARY KEY (`id`), KEY `user_id` (`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; idとuser_idを条件にするクエリであれば、上記制約を満たすため、 KEY `id_user_id_idx` (`id`,`user_id`) の複合クエリを定義すれば良いのでしょうか? また、idとuser_idとfile_idを条件にするクエリも考慮に入れた場合、 テーブル定義は以下のようにするのでしょうか? CREATE TABLE IF NOT EXISTS `data` ( `id` int(10) NOT NULL default '0', `user_id` int(10) NOT NULL default '0', `file_id` int(10) NOT NULL default '0', `name` text collate utf8_unicode_ci NOT NULL default '', PRIMARY KEY (`id`), KEY `user_id` (`user_id`), KEY `id_user_id_idx` (`id`,`user_id`), KEY `id_user_id_file_id_idx` (`id`,`user_id`,`file_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 最後に、create table 時のインデックスの指定は、 INDEX `user_id` (`user_id`), のようにもできますが、INDEXとKEYの違いは何かあるのでしょうか。

    • ベストアンサー
    • MySQL
  • MySQLでの文字化けについて

    すいません、教えてください。 PHP(PHP-5.2.4)でCSVファイル を読み込んでMySQL(4.1.22)に INSERTしているのですが文字化けします。 SJIS→utf8_general_ciです。 いろいろ調べて ~ $wk[$i] =mb_convert_encoding($csvfile[$i],'UTF-8','SJIS-win'); ~ とかやってみたのですがうまくいきません。 どなたかよろしくお願いします。

    • 締切済み
    • PHP
  • UTF8のPHPコードから日本語をINSERTするとphpMyAdmin上で文字化けしてしまう

    ・WindowsXP(SP2)IIS5.1 ・PHP 5.2.5 Win32 ・MySQL 5.1.22 RC Win32 ・phpMyAdmin 2.11.4 多言語(日本語と中国語)を扱える簡単なシステムを試作しているのですが、 test1.php(UFT8-BOM無し)からINSERTしたレコードをphpMyAdminから閲覧 すると日本語が「&egrave;&sup2;&iexcl;&aring;›&pound;&aelig;&sup3;•&auml;&ordm;&ordm;&aelig;」などと文字化けしまくっています。 test2.phpからSELECTすると、まったく文字化けなく呼び出せます。 また、phpMyAdminから直接INSERTしたレコードば文字化けしません。 当初、MySQL4.1.22-win32や、phpMyAdmin 2.8.2.4だったので、 冒頭の最新バージョンにしたりもしてみましたがだめでした。 過去ログや、Webで昨日さんざん調べてみて、確認したのは以下の設定です。 (1) C:\Program Files\MySQL\MySQL Server 5.1\my.ini: [mysqld] character-set-server = utf8 collation-server = utf8_general_ci init-connect = SET NAMES utf8 [mysqldump] default-character-set = utf8 [mysql] default-character-set = utf8 (2) C:\Inetpub\wwwroot\phpMyAdmin\libraries\config.default.php $cfg['DefaultLang'] = 'utf-8'; $cfg['DefaultConnectionCollation'] = 'utf8_general_ci'; $cfg['DefaultCharset'] = 'utf-8'; (3) MySQL Server Instance Config Wizard UTF8を選択しました(MySQL の文字セット: UTF-8 Unicode (utf8)) MySQL 接続照合順序 utf8_general_ci

    • ベストアンサー
    • PHP