MySQLのdrop tableでは複数のテーブルを一気に削除できる
タイトル通りなんですが、今までは複数のテーブルを削除する時は
> drop table hoge; > drop table fuga;
なんてやってましたが、
> drop table hoge fuga;って書けるんですね。豆知識。
タイトル通りなんですが、今までは複数のテーブルを削除する時は
> drop table hoge; > drop table fuga;
なんてやってましたが、
> drop table hoge fuga;って書けるんですね。豆知識。
最近Gitの共有リポジトリを構築する機会があったのですが、以下のような感じで運用しています。
いちいちサーバ側にユーザ追加して、gitリポジトリのディレクトリにパーミッション付与するよりこっちの方がたぶん楽。
Perlで日付関連の処理をする代表的なモジュールにDateTimeというものがありますが、メモリ消費量が激しいのがずっと気になっていました。でで、Time::Pieceが5.10.1からPerlに標準添付になったという話を聞いて、乗り換えようかどうか検討しています。Perlメモ/Time::Pieceモジュール – Walrus, Digit.を見ると、DateTimeでできることは大体できるので、以下のユースケースでの速度面を測ってみます。
環境は以下で、ベンチマークのスクリプトは最後に載せてあります。
こちらのgtop.plを使って測ります。
$ gtop.pl 'use DateTime'
10.2M : use DateTime$ gtop.pl 'use Time::Piece'
2.5M : use Time::Pieceおおお、なんと4分の1!
$ ./benchmark_datetime.pl now Benchmark: running now_datetime, now_time_piece for at least 3 CPU seconds... now_datetime: 4 wallclock secs ( 3.03 usr + 0.00 sys = 3.03 CPU) @ 3149.83/s (n=9544) now_time_piece: 2 wallclock secs ( 2.58 usr + 0.53 sys = 3.11 CPU) @ 52694.86/s (n=163881) Rate now_datetime now_time_piece now_datetime 3150/s -- -94% now_time_piece 52695/s 1573% --
15倍!
$ ./benchmark_datetime.pl add Benchmark: running add_datetime, add_time_piece for at least 3 CPU seconds... add_datetime: 3 wallclock secs ( 3.05 usr + 0.00 sys = 3.05 CPU) @ 1853.44/s (n=5653) add_time_piece: 3 wallclock secs ( 2.76 usr + 0.42 sys = 3.18 CPU) @ 54969.81/s (n=174804) Rate add_datetime add_time_piece add_datetime 1853/s -- -97% add_time_piece 54970/s 2866% --
Time::Pieceの圧倒的勝利。28倍!
$ ./benchmark_datetime.pl subtract Benchmark: running subtract_datetime, subtract_time_piece for at least 3 CPU seconds... subtract_datetime: 3 wallclock secs ( 3.00 usr + 0.00 sys = 3.00 CPU) @ 4065.00/s (n=12195) subtract_time_piece: 4 wallclock secs ( 3.15 usr + 0.00 sys = 3.15 CPU) @ 132329.84/s (n=416839) Rate subtract_datetime subtract_time_piece subtract_datetime 4065/s -- -97% subtract_time_piece 132330/s 3155% --
引き算もTime::Pieceの方が圧倒的に速いですね。
$ ./benchmark_datetime.pl compare Benchmark: running compare_datetime, compare_time_piece for at least 3 CPU seconds... compare_datetime: 3 wallclock secs ( 3.04 usr + 0.00 sys = 3.04 CPU) @ 47709.21/s (n=145036) compare_time_piece: 4 wallclock secs ( 3.09 usr + -0.01 sys = 3.08 CPU) @ 173623.70/s (n=534761) Rate compare_datetime compare_time_piece compare_datetime 47709/s -- -73% compare_time_piece 173624/s 264% --
$ ./benchmark_datetime.pl stringify Benchmark: running stringify_datetime, stringify_time_piece for at least 3 CPU seconds... stringify_datetime: 3 wallclock secs ( 3.00 usr + 0.00 sys = 3.00 CPU) @ 44470.33/s (n=133411) stringify_time_piece: 3 wallclock secs ( 2.45 usr + 0.66 sys = 3.11 CPU) @ 116681.35/s (n=362879) Rate stringify_datetime stringify_time_piece stringify_datetime 44470/s -- -62% stringify_time_piece 116681/s 162% --
総じてDateTimeよりTime::Pieceの方が高い性能を叩き出しました。速度にシビアな状況ではTime::Pieceを使った方が良いと感じました。こういう罠もあるみたいなので気をつけなくてはいけないところもありますが… インタフェースはどちらも綺麗に出来ているので使い勝手としては同じぐらいかなと思います。それにしてももっと速くTime::Pieceを検証しておけばよかったと思う今日この頃です。
#!/usr/bin/env perl use strict; use warnings; use Benchmark qw(cmpthese timethese); use DateTime; use Time::Piece; use Time::Seconds; my $timezone = DateTime::TimeZone->new(name => 'local'); #----------------------# # now #----------------------# sub now_datetime { my $now = DateTime->now(time_zone => $timezone); } sub now_time_piece { my $now = localtime; } #----------------------# # add #----------------------# my $add_dt = DateTime->now(time_zone => $timezone); sub add_datetime { $add_dt->add(days => 1); } my $add_tp = localtime; sub add_time_piece { $add_tp += ONE_DAY; } #----------------------# # subtract #----------------------# my $sub_dt1 = DateTime->now(time_zone => $timezone); my $sub_dt2 = DateTime->new( year => 2008, month => 12, day => 1, ); sub subtract_datetime { my $dur = $sub_dt1->subtract_datetime($sub_dt2); } my $sub_tp1 = localtime; my $sub_tp2 = Time::Piece->strptime('2008-12-01', '%Y-%m-%d'); sub subtract_time_piece { my $sec = $sub_tp1 - $sub_tp2; } #----------------------# # compare #----------------------# my $compare_dt1 = DateTime->now(time_zone => $timezone); my $compare_dt2 = DateTime->now(time_zone => $timezone); sub compare_datetime { my $result = DateTime->compare($compare_dt1, $compare_dt2) <= 0; } my $compare_tp1 = localtime; my $compare_tp2 = localtime; sub compare_time_piece { my $result = $compare_tp1 <= $compare_tp2; } #----------------------# # stringify #----------------------# my $now_dt = DateTime->now(time_zone => $timezone); sub stringify_datetime { $now_dt->strftime("%Y-%m-%d"); } my $now_tp = localtime; sub stringify_time_piece { $now_tp->strftime("%Y-%m-%d"); } #----------------------# # main #----------------------# my $mode = shift @ARGV || 'now'; my $count = shift @ARGV || -3; if ($mode eq 'now') { cmpthese timethese $count, { 'now_datetime' => \&now_datetime, 'now_time_piece' => \&now_time_piece, }; } elsif ($mode eq 'add') { cmpthese timethese $count, { 'add_datetime' => \&add_datetime, 'add_time_piece' => \&add_time_piece, }; } elsif ($mode eq 'subtract') { cmpthese timethese $count, { 'subtract_datetime' => \&subtract_datetime, 'subtract_time_piece' => \&subtract_time_piece, }; } elsif ($mode eq 'compare') { cmpthese timethese $count, { 'compare_datetime' => \&compare_datetime, 'compare_time_piece' => \&compare_time_piece, }; } elsif ($mode eq 'stringify') { cmpthese timethese $count, { 'stringify_datetime' => \&stringify_datetime, 'stringify_time_piece' => \&stringify_time_piece, }; }
Now Text::MicroTemplate is even faster than HTML::Template::Pro – use GFx::WebLog;
Text::MicroTemplate 0.10で動作速度が改善されたとのことなので、自分のところでもベンチマークしてみました。
$ perl benchmark_templates.pl 1 Perl/5.10.0 (x86_64-linux-gnu-thread-multi) HTML::Template/2.9 HTML::Template::Compiled/0.94 HTML::Template::Pro/0.92 Template/2.20 Text::MicroTemplate/0.10 Benchmark: running HT, HT::C, HT::Pro, MT, TT for at least 1 CPU seconds... HT: 1 wallclock secs ( 1.03 usr + 0.00 sys = 1.03 CPU) @ 1094.17/s (n=1127) HT::C: 1 wallclock secs ( 1.03 usr + 0.00 sys = 1.03 CPU) @ 11598.06/s (n=11946) HT::Pro: 2 wallclock secs ( 0.82 usr + 0.29 sys = 1.11 CPU) @ 17611.71/s (n=19549) MT: 1 wallclock secs ( 0.96 usr + 0.08 sys = 1.04 CPU) @ 15904.81/s (n=16541) TT: 1 wallclock secs ( 1.08 usr + 0.00 sys = 1.08 CPU) @ 7110.19/s (n=7679) Rate HT TT HT::C MT HT::Pro HT 1094/s -- -85% -91% -93% -94% TT 7110/s 550% -- -39% -55% -60% HT::C 11598/s 960% 63% -- -27% -34% MT 15905/s 1354% 124% 37% -- -10% HT::Pro 17612/s 1510% 148% 52% 11% --
何回かやったのですが、自分の環境ではまだHTML::Template::Proが速いみたい。でも僅差なのでまったく気にならないレベルですね。とにかくgfxさん++すぎる。
PerlでWebアプリを作る時のテンプレートエンジンをどれにしようか相変わらず模索中なのですが、以下の2つのエントリーで動作速度とメモリについて調べた結果、どうやらText::MicroTemplateとHTML::Template::Proのどちらかを選択するのが良いだろうと思っています。
「<TMPL_IF>、<TMPL_LOOP>で改行のコントロールが難しい」というのは、例えば以下のテンプレートファイルがあって、それを実際に出力した時のHTMLに改行が入ってしまう、ということです。
テンプレートファイル
<html> <head></head> <body> <TMPL_IF NAME=hoge> hoge </TMPL_IF> </body> </html>
出力されるHTML
<html> <head></head> <body> #ここに改行 hoge #ここにも改行 </body> </html>
出力するのがHTMLであればそんなに問題はないのですが、メールの文面をテンプレートエンジンで動的に生成したい場合、改行が実直に反映されてしまうので、いつもどうしようか悩んでしまいます。この改行のためにHTMLの生成とメールの生成で別々のテンプレートエンジン使うのも微妙ですし。
もしかするとHTML::Template::Proの filter 機能でなんとかできるのかもしれませんが、まだそこまでは考えられてないです。というわけで相変わらずテンプレートエンジンどうしようか悩み中…
Text::MicroTemplateの速度を簡単にベンチマークでText::MicroTemplateの動作速度を簡単にベンチマークしましたが、今回はメモリ使用量を他のテンプレートエンジンと比較してみました。環境はUbuntu 9.04 amd64, Perl 5.10.0 で、GTopを使って測っています。
独自に作ったスクリプト(use_memory_size.pl)でuse時のメモリ使用量を測ってみます。
$ ./use_memory_size.pl
3.2M : use HTML::Template
11.7M : use HTML::Template::Compiled
2.5M : use HTML::Template::Pro
264k : use Text::MicroTemplate
3.6M : use TemplateHTML::Template::Compiledは多くのモジュールで構成されているので、メモリ使用量が多そうな感じです。一方、ソースコードがとてもコンパクトな Text::MicroTemplate は他のテンプレートエンジンと比べてメモリ使用量が一桁少ない。これはすごい。
use_memory_size.pl
#!/usr/bin/env perl use strict; use warnings; for my $module (qw(HTML::Template HTML::Template::Compiled HTML::Template::Pro Text::MicroTemplate Template)) { system "gtop.pl 'use $module'"; }
(プロセスのメモリ使用量を調べるために必要なGTopモジュール(およびlibgtop2)をインストールして、下記スクリプトをgtop.plとしてどこかパスの通ってるところに保存しておいてください)
gtop.pl
#!/usr/bin/env perl use strict; use warnings; use GTop; unless (@ARGV) { print STDERR "Argument required.\n"; exit 1; } my $gtop = GTop->new; my $before = $gtop->proc_mem($$)->size; eval $ARGV[0]; die $@ if $@; my $after = $gtop->proc_mem($$)->size; my $diff = GTop::size_string($after - $before); print "$diff : $ARGV[0]\n";
モジュールをuseした時のメモリ使用量だけでなく、newしてoutputした後のメモリ使用量も調べてみました。結果は以下になります。
$ ./new_memory_size.pl 3.2M : use HTML::Template;my $t = HTML::Template->new(filename => q{template_speed_file.ht});my $s = $t->output; 11.7M : use HTML::Template::Compiled;my $t = HTML::Template::Compiled->new(filename => q{template_speed_file.ht});my $s = $t->output; 2.5M : use HTML::Template::Pro;my $t = HTML::Template::Pro->new(filename => q{template_speed_file.ht});my $s = $t->output; 796k : use Text::MicroTemplate::File;my $t = Text::MicroTemplate::File->new;my $s = $t->render_file(q{template_speed_file.mt})->as_string;; 11.4M : use Template;my $t = Template->new;$t->process(q{template_speed_file.tt}, {}, \my $s);
相変わらずText::MicroTemplateは良好な成績ですね。あまりメモリを積んでいないマシンでもこれなら安心して使えそうな感じです。HTML::Template::Proも2.5MBと省メモリですね。スピードも爆速なので、テンプレートにゴリゴリPerlのコードを書く必要がない場合はこれが一番よいかもしれません。
new_memory_size.pl
#!/usr/bin/env perl use strict; use warnings; # HTML::Template my $ht = <<'...'; use HTML::Template; my $t = HTML::Template->new(filename => q{template_speed_file.ht}); my $s = $t->output; ... # HTML::Template::Compiled my $htc = <<'...'; use HTML::Template::Compiled; my $t = HTML::Template::Compiled->new(filename => q{template_speed_file.ht}); my $s = $t->output; ... # HTML::Template::Pro my $htp = <<'...'; use HTML::Template::Pro; my $t = HTML::Template::Pro->new(filename => q{template_speed_file.ht}); my $s = $t->output; ... # Text::MicroTemplate my $mt = <<'...'; use Text::MicroTemplate::File; my $t = Text::MicroTemplate::File->new; my $s = $t->render_file(q{template_speed_file.mt})->as_string;; ... # Template my $tt = <<'...'; use Template; my $t = Template->new; $t->process(q{template_speed_file.tt}, {}, \my $s); ... for my $code ($ht, $htc, $htp, $mt, $tt) { $code =~ s/\n//g; system qq{gtop.pl '$code'}; }
インフラエンジニアじゃないけどインフラエンジニア勉強会 hbstudy#5に参加してきました。もともとこのイベントには参加したいなぁと思っていて、参加登録したらいいタイミングで松信さんが講演することにw 貴重なMySQLのチューニングの話が生で聞けてとてもよかったよかった。
あと、最初にPostgreSQLの話をしていた永安さんのセッションもよかった。普通DBの入門の話ってあまりつっこんだ運用の話は出てこないと思うのですが、運用を意識した入門編でこういうのはすごい貴重だったのではないかと。
永安さんの話はスライドを見てもらえばほぼ全てわかります。スライドが充実し過ぎていてあまりメモを取っていなかったのですが、最近のポスグレはAuto Vacuumなんて仕組みがあって、あまりVacuumを意識しなくてよいのだなぁと。あとポスグレもチューニングはいかに共有バッファをうまく使うかっていうところで、あんまりMySQLと変わらないんだなって思いました。
資料(PDF)
MySQLのチューニングの基本はデータサイズを小さくしていかにメモリにのっけるか、という話。たとえば、日時を格納するカラムはDATETIME(8byte使用)じゃなくてTIMESTAMP(4byte)を使えとか。statusみたいな1/0しか入らないカラムは文字列型じゃなくてTINYINTかENUM使えとか。ちなみに日時は2038年問題が気にならないのであれば、UNIXTIME化してINT型のフィールドにしてしまうという荒技もありますよね。アプリケーション側でいちいち変換しなくてはいけないですが。
あと「巨大なTEXT/BLOBはクエリ効率を悪化させる」という話で、巨大なデータを格納するカラムは別テーブルにすると、それ以外のカラムのデータをSELECTするときに悪影響が出ないらしい。ちょっとどういう話か失念してしまったので、資料が公開されたら復習します。一定以上の大きさのテキストフィールドを別領域に保存するストレージエンジンとして、Falcon, PBXTがあるとのこと。ちなみに、HDDが一秒間に処理できるランダムI/Oはせいぜい数百ぐらいなので、とても遅いですと。
あとは実データを引かずにCovering Index(インデックスだけを読む検索)でうまく処理する方法もあるそうで、
というメリットデメリットがあるそうです。
途中から殴り書きですが、TIMESTAMP型が4byteとDATETIMEの半分で済むことにこの日初めて知りました。その他Covering Indexなど、知らなかったテクニックなのでとても勉強になりました。あとSSDは本当もうすぐそこまで来ていて、これを入れるだけで数倍DBのI/Oが速くなることを考えるとすごいなぁと。しかし色々ベンチ取られていて、すごく説得力のあるお話でした。この人にコンサル頼んだらいくらかかるんだろう…
コメント