MySQLのdrop tableでは複数のテーブルを一気に削除できる

2009 年 12 月 24 日 oinume コメントはありません

タイトル通りなんですが、今までは複数のテーブルを削除する時は

> drop table hoge;
> drop table fuga;

なんてやってましたが、

> drop table hoge fuga;

って書けるんですね。豆知識。

カテゴリー: MySQL タグ:

Gitの共有リポジトリを運用する場合の個人的なベストプラクティス

2009 年 12 月 17 日 oinume コメントはありません

最近Gitの共有リポジトリを構築する機会があったのですが、以下のような感じで運用しています。

  • gitプロトコルではなくsshでアクセス(ポート開けるのだるいので)
  • サーバ側にgitユーザを作って、アクセスさせたい人にsshの公開鍵をもらってそれを /home/git/.ssh/authorized_keys に追加して公開鍵認証
  • git clone ssh://git@lampetty.net/var/cache/git/hoge.git みたいな感じでclone

いちいちサーバ側にユーザ追加して、gitリポジトリのディレクトリにパーミッション付与するよりこっちの方がたぶん楽。

カテゴリー: Git, Linux タグ: ,

PerlのDateTimeとTime::Pieceモジュールのベンチマーク

2009 年 12 月 6 日 oinume コメントはありません

Perlで日付関連の処理をする代表的なモジュールにDateTimeというものがありますが、メモリ消費量が激しいのがずっと気になっていました。でで、Time::Pieceが5.10.1からPerlに標準添付になったという話を聞いて、乗り換えようかどうか検討しています。Perlメモ/Time::Pieceモジュール – Walrus, Digit.を見ると、DateTimeでできることは大体できるので、以下のユースケースでの速度面を測ってみます。

環境は以下で、ベンチマークのスクリプトは最後に載せてあります。

  • OS: Ubuntu 9.04 amd64
  • Perl: 5.10.0 x86_64-linux-gnu-thread-multi
  • DateTime 0.51
  • Time::Piece 1.15

use 時のメモリ使用量

こちらの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を検証しておけばよかったと思う今日この頃です。

ベンチマークスクリプト(benchmark_datetime.pl)

#!/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,
    };
}
カテゴリー: Perl タグ:

Text::MicroTemplate 0.10で速度が速くなっている件

2009 年 11 月 21 日 oinume コメントはありません

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 タグ:

Text::MicroTemplateとHTML::Template::Proの比較

2009 年 11 月 21 日 oinume コメントはありません

PerlでWebアプリを作る時のテンプレートエンジンをどれにしようか相変わらず模索中なのですが、以下の2つのエントリーで動作速度とメモリについて調べた結果、どうやらText::MicroTemplateとHTML::Template::Proのどちらかを選択するのが良いだろうと思っています。

Text::MicroTemplateの良い点

  • Perlのコードが書けるので自由度が高い
  • そこそこ速い
  • 省メモリ
  • デフォルトでHTMLエスケープしてくれるのでセキュリティ的にもグッド
  • コードがシンプルなので拡張しやすい
  • loopやifで改行の制御が出来る(と ? )

HTML::Template::Proの良い点

  • 文法がシンプル
  • 爆速
  • そこそこ省メモリ
  • register_functionでテンプレート内から呼び出せる関数が登録できるので、拡張性はそれなりにある

Text::MicroTemplateのイマイチな点

  • 自由度が高い分、色々できてしまう(Viewにロジックをガリガリ書いたりとか)
  • Includeがデフォルトでは出来ない(Text::MicroTemplate::Extended使えば似たようなことはできる)

HTML::Template::Proのイマイチな点

  • <TMPL_IF>、<TMPL_LOOP>などの制御を書く時の改行のコントロールが難しい
  • デフォルトではHTMLエスケープがかからないので、自前で自動エスケープのロジックを書くかテンプレート側で毎度エスケープしなくてはいけない

「<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 機能でなんとかできるのかもしれませんが、まだそこまでは考えられてないです。というわけで相変わらずテンプレートエンジンどうしようか悩み中…

カテゴリー: Perl タグ:

Text::MicroTemplateのメモリ使用量をベンチマーク

2009 年 11 月 15 日 oinume コメントはありません

Text::MicroTemplateの速度を簡単にベンチマークでText::MicroTemplateの動作速度を簡単にベンチマークしましたが、今回はメモリ使用量を他のテンプレートエンジンと比較してみました。環境はUbuntu 9.04 amd64, Perl 5.10.0 で、GTopを使って測っています。

useした時のメモリ使用量

独自に作ったスクリプト(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 Template

HTML::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";

newしてレンダリングさせた後のメモリ使用量

モジュールを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'};
}
カテゴリー: Perl タグ:

hbstudy#5に参加してきました

2009 年 11 月 15 日 oinume コメントはありません

インフラエンジニアじゃないけどインフラエンジニア勉強会 hbstudy#5に参加してきました。もともとこのイベントには参加したいなぁと思っていて、参加登録したらいいタイミングで松信さんが講演することにw 貴重なMySQLのチューニングの話が生で聞けてとてもよかったよかった。

あと、最初にPostgreSQLの話をしていた永安さんのセッションもよかった。普通DBの入門の話ってあまりつっこんだ運用の話は出てこないと思うのですが、運用を意識した入門編でこういうのはすごい貴重だったのではないかと。

PostgreSQL安定運用のコツ2009

永安さんの話はスライドを見てもらえばほぼ全てわかります。スライドが充実し過ぎていてあまりメモを取っていなかったのですが、最近のポスグレはAuto Vacuumなんて仕組みがあって、あまりVacuumを意識しなくてよいのだなぁと。あとポスグレもチューニングはいかに共有バッファをうまく使うかっていうところで、あんまりMySQLと変わらないんだなって思いました。

Linux 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(インデックスだけを読む検索)でうまく処理する方法もあるそうで、

  • テーブルのレコードにアクセスする必要がなくなるので、高速になる
  • Indexのサイズが大きくなるので、更新のコストが高くなる
  • Limit句を使うときにも効果がある

というメリットデメリットがあるそうです。

  • メモリを十分に確保してダイレクトI/Oを活用する
  • オンライン処理のあとに、バッチ処理で巨大なテーブルに対してフルスキャンするのは問題がある
  • バッチ処理によるバッファプールが占有され、オンラインのバッファプールが追い出されてしまうため
  • OOM Killerに注意する
  • ダイレクトI/Oを使うとプロセス内にデータが置かれるので、プロセスのサイズが大きくなる
  • DBサーバとしてはファイルシステムキャッシュを縮小してほしい
  • # echo 0 > /proc/sys/vm/swappiness = 0
  • -> Direct I/Oとセットで使うことが多い
  • cpで大きいファイルをコピー
  • cpに対してファイルシステムキャッシュが使われる
  • InnoDBのプロセスのデータがスワップに追い出される->これは避けたい
  • ファイルシステムはext3
    • もっとも使われていて安全
    • dir_index, noatime(relatime)
    • xfsはDirect I/Oだと並列で書き込める
    • xfsは巨大なファイルのコピーがはやい
    • でもxfs使っている人少なすぎなので、おすすめできないw
  • 監視の方法
    • iotop: プロセス単位でI/O量を取る kernel 2.6.20以降
    • ネットワーク統計: MySQL Cluster使う人には必要かも
    • mtstat: 一秒おきに受信/送信byte数を表示
    • /proc/net/dev をみればわかる情報
  • SSD
    • ランダムリードはHDD: 200回にたいして、25000回のI/O (Intel X25E)
    • 書き込み性能は製品による差が激しい
    • write cache必須
    • バッテリーで守れていることが重要。RAIDコントローラに任せるものとSSD自身で持つものがある(RAID Controllerの場合はそれがSSDに対応していることが重要)
    • SSDは並列性が重要。Crystalなんとかのベンチはシングルプロセスの話なのであてにならない
    • PCI-E型SSDにも注目 -> I/Fの速度が速い(300MB -> 2GB)

途中から殴り書きですが、TIMESTAMP型が4byteとDATETIMEの半分で済むことにこの日初めて知りました。その他Covering Indexなど、知らなかったテクニックなのでとても勉強になりました。あとSSDは本当もうすぐそこまで来ていて、これを入れるだけで数倍DBのI/Oが速くなることを考えるとすごいなぁと。しかし色々ベンチ取られていて、すごく説得力のあるお話でした。この人にコンサル頼んだらいくらかかるんだろう…

カテゴリー: MySQL タグ: ,
Pages: << 1 2 3 4 5 6 7 8 ...18 19 20 >>