こんばんわ。かーつんです。
SQL負荷って、考えたことありますか?
条件などにもよりますが、
SELECT、INSERT、DELETE、UPDATE順に徐々に重くなります。
理由は簡単。
SELECT=検索
INSERT=挿入+インデックスレコード追加
DELETE=検索+削除+インデックスレコード更新
UPDATE=検索+更新+インデックスレコード更新
と、処理が増えるからです。
例えば、UPDATEを100回投げるなら、
TRUNCATE+INSERTの方が早い事もあります。
要するに更新が一番重く、検索が一番早いわけですね。
で、よくあると思いますが、
あればUPDATEかけて、なければINSERTというのを
SELECT+UPDATE+INSERTの組み合わせでやってる方が多いと思います。
そんなときは、迷わずREPLACEを使いましょう。
REPLACEは検索+[更新|挿入]+インデックス[更新|挿入]です。
上の例だと、
SELECT+(UPDATE or INSERT)=検索+[(検索+更新)|挿入]
REPLACE=検索+[更新|挿入]
どちらが早いか一目瞭然ですよね。
検索一回分REPLACEの方が早いです。
もちろん条件的に無理。ということもありますが、
使えるときは使っちゃった方が、処理が早いです。
プログラムで、
ファイルレコード1件ごとにSELECT投げて、
UPDATEかINSERTか判断して実行して、
これを1000回繰り返す。コレは悪です。やってたら犯罪です。
一括でファイル読み込んで、
一括でSELECT投げて、
REPLACEで一気に1000回更新
置き換えれる時は迷わず変えてしまいましょうネ
以上。か^-^つんがお送りしました。
かーつん MySQL, データベース
二日連続で失礼します。
チョコボールです。
昨日の天気は荒れに荒れてましたね。。
今も荒れてますが。。
長時間雷鳴りっぱなしの豪雨!
住まいは東京の西の方なのでモロに影響受けました。。
PCが壊れるとまずいので家帰ってからずっとPCの電源抜いてました。
というのも、落雷で家電製品が壊れた…なんて話をよく聞くからです。
一か月ほど前、近所で落雷があり、同じアパートの住人がPCの電源が立ち上がらなくなった…と悔やんでいました。
その時、自分は家にいましたが、危険を感じて電源引っこ抜いていたので運よく無事でした。。
ここまで落雷が多いと、雷サージ対策をしなきゃまずいって気持ちになってきます。
今度電気屋に行った時は絶対買おう。。
昨日から久々にCakePHPを触ることになりました。
弊社コマースシステムの管理機能追加です。
現在のCakePHPのバージョンは1.2ですが、弊社のシステムはバージョン1.1で構築したもの。
ほぼ初心者の頃、いきなりCakePHPを触っていた自分はDB関係のデータ取得等はメソッドを使いまくっていたのでSQLになかなか慣れませんでした。
他人が書いたSQL文中のJOINという文字を見るとどうなってるか分からず、拒絶反応を起こしてしまう…というようなひどい状態が続いていました。
テーブルを結合してデータを取ってきてくれたりするCakePHPのアソシエーション機能は非常に便利ですが、理解しないままこれを利用しているといつまでたってもSQLについて詳しくなれません。。
SQLはできるだけベタに近い状態で書いた方がフレームワークを理解していない人でもすぐ理解でき、保守は楽だと思います。
無駄なSQLをたくさん流すと負荷がかかって遅くなりますし。。
処理が重くなるところはできるだけ簡素で効率のいいSQLを書きたいものです。
一通りWEBアプリケーションに精通している方達はこのようなフレームワークを使った方が高速に開発できると思います。
CakePHPの好きなところはすごく好きなんですけどね。。
システムとして見るとかなり勉強にもなります。
パフォーマンス性や保守性を重視するか、高速開発を重視するか…。
ただ間違いないと思うことは、処理が重いシステムは誰も嫌がる…とういことです。
MoriMoriMoriMori MySQL, PHP, Tips, データベース
はいどうも
のびーにょです
表題のとおりなんですけど、皆さんアクセスログってどう処理してます?
僕の場合はシステム側でDBに取るようにしてます。
オーバーヘッドとか色々考えなきゃだめな部分ありますけど、割と便利です。
まず、Apacheの標準のアクセスログだとPOSTの値がとれません。
※こんな方法もあったりしますが
http://neta.ywcafe.net/000607.html
で、僕はアクセスすべてをDBに保存しています。
レコード数が多くなりすぎたりすると処理に時間がかかってしまいますので月別、週別でアーカイブしていったり、場合によっては日別でテーブルを分けるなどの処理が必要ですが・・・
以下bash
#!/bin/bash
mysql -uユーザ名 -pパスワード rutty_test -hホスト << EOT
ALTER TABLE access_log RENAME AS access_log_`date +%Y_%m_%d`;
CREATE TABLE \\`access_log\\` (
\\`id\\` int(11) unsigned NOT NULL auto_increment,
\\`access_date\\` datetime NOT NULL,
\\`carrier\\` enum('DOCOMO','EZWEB','SOFTBANK','OTHER')NOT NULL default 'OTHER',
\\`u_id\\` int(11) unsigned default NULL,
\\`jb\\` varchar(255) NOT NULL,
\\`parameter\\` longtext,
PRIMARY KEY (\\`id\\`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
EOT
とかのBASHを日別とか週別とか月別とかで実行してやればテーブルのサイズはそんなに大きくなることはないと思います。
フレームワークとか使っているならPOSTとかGETで受け取るものはすべてラッピングできると思うので、そこでDBにほりこんでおけばすべての値を得ることができると思います。
アクセスログをDBに入れておくと何が嬉しいか
集計するとき楽なんですよね。
ちなみに上にあるアクセスログのテーブルのカラムの一つ”jb”ってのは僕の使っているフレームワークののページ名です。
それ集計するだけで日別の各ページのアクセス数がとれるのですごく楽です。
携帯メインなのでキャリアの情報も格納しておけばさらにキャリア別でとれるし。
さっきのBASHを少し変えて、1週間前のテーブルなら削除するとかの処理入れておけばDBもそんなに大きくならなくていいかなーと思います。
集計結果を保存しておくテーブルは当然別につくり、cronとかで日別集計、週別集計、月別集計のバッチ組んでやれば古いデータは必要ないですし、CDなりDVDなりに焼いてやればHDDも圧迫しませんし。
POSTの値も保存できるので作ったアプリケーションの障害時に何が原因かってのも追えますしね。
結構お勧めです。
のびーにょ Apache, MySQL, Tips, データベース
おなかのお肉が(ry
のびーにょです
こんばんは
前回のエントリーからもつながりますが、またもや保守に関することです
DBを使う場合、いろいろなフラグが出てくると思います。
男性なのか、女性なのか。
会員なのか、非会員なのか。
新規受け付け、入金待ち、キャンセル、取り寄せ中、発送済み、入金済み
等など・・・
その場合、フラグをint型で持たせる人も多いかと思います。
かまわないと思います。
コメント残すのであれば ですけど。
ドキュメントに残してるからいいや とか、ちょっと勘弁してほしいです。
そのドキュメント、いつのドキュメントですか?ってなるんですよ。正直コメントも一緒ですけど。
DBにもコメント残す機能ありますしね。
SHOW FULL COLUMNS FROM テーブル名
で確認できますね、MySQLなら。
追加するなら
ALTER TABLE m_user CHANGE gender gender TINYINT
NOT NULL DEFAULT "1" COMMENT '1:male 2:female';
って感じですね。
つか、フラグで分けるなと。
ENUM使ってくださいと。
男女なら
ENUM(’MALE’,'FEMALE’)
会員非会員なら
ENUM(’YES’,'NO’)
新規受け付け、入金待ち、キャンセル、取り寄せ中、発送済み、入金済みなら
ENUM(’SHINKI’,'MACHI’,'CANCEL’,'TORIYOSE’,'END’,'NYUKINN’)
とかとか(最後のはあんまり良くないけど・・・数字よりは断然ましかと)
正直保守する時にソースすべて追いつつフラグの内容判断とか萎えるだけなので辞めてほしいです。
のびーにょ MySQL, データベース
チョコボールakaモリモリ~です。
7月から携帯コンテンツの開発に加わることになりました。
今までは管理画面系が多かったので携帯に関する知識はほとんど無かったのですが、携帯3キャリアに対応していくためのコーディングやセッションの引き回しについてなど、少しずつ覚えてきました。
今回はデータベースについて思うこと…を。
今まではDB操作はずっとphpMyAdminに頼ってたんですが、コンソールを使うようにと指示が出て、最近はひたすらSSHでカタカタとやってます。
慣れてくるとサクサク処理出来て快適ですね。
早いというか、それが通常の処理の早さってことなんでしょうけど。。
個人的に作ってるサイトはSSHが使えないレンタルサーバーなのでDB操作はphpMyAdminを通してやるしかないのが残念です。
自分は業務でデータベース設計をすることはありませんが、実際に使う時のことを考えて、できるだけ複雑なJOINやサブクエリをさせないようにうまいこと設計しないと、のちのちレコードが増えてきた時にパフォーマンスにモロに影響が出る、と実感しました。
あまりにも関連テーブルを分けすぎるとSQL組む時、かなり複雑になります…。
データが1000レコードでSELECT文、オフセット10でデータひっぱってくるのに10秒以上かかる。
こんなシステムに遭遇。。
発行されたSQL文を見てみると、JOIN、サブクエリが複雑に絡み合って恐ろしいことになってました。
一つの複雑なSQL文で全てやろうとするよりもSQLを何回かに分けてプログラム側でごにょごにょやると取り敢えずパフォーマンスは改善しそうな予感です。
今後データベース設計する機会があったら活かせるとよいなーと思います。
MoriMoriMoriMori Linux, MySQL, PHP, データベース