SQLログには以下のような記録が残る。
LOG: statement: INSERT INTO history (tid,bid,aid,delta,mtime) VALUES (4,1,25891,8417,CURRENT_TIMESTAMP); LOG: duration: 72.786 ms |
ここから,このINSERT文の実行には72ミリ秒ほどかかっていることが分かる。これを利用すると,性能的にボトルネックになっているSQL文を見つけることもできる。
pgFouineとは
![]() 写真1●pgFouineのWebサイト [画像のクリックで拡大表示] |
そこで開発されたのがpgFouineだ。pgFouineを使えばSQLログを素早く解析し,レポートを作成できる。結果をグラフを交えてビジュアルに表示することも可能だ(写真1)。
ちなみにFounieはフランス語で貂(テン)を意味する。作者はフランスのリオン在住,弱冠25才のGuillaume Smet氏だ。開発はpgpool同様,pgfoundry.orgでホスティングされており,http://pgfouine.projects.postgresql.org/ で開発サイトにアクセスできる。
インストール
評価に使ったのは本稿執筆時点で最新版のバージョン0.5である。以下からダウンロードできる。
http://pgfoundry.org/frs/download.php/828/pgfouine-0.5.tar.gz
インストールは極めて容易で,単に好みの場所にtar ballを展開するだけだ。展開すると,以下のようなファイルやディレクトリができる。
AUTHORS ChangeLog README include/ pgfouine.spec tests/ COPYING INSTALL THANKS pgfouine.php* rpm-specific/ |
pgfouine.php がツール本体で,PHPで書かれたスクリプトになっている。したがって実行にはPHPが必要だ。評価に使ったのはPHP 4.4.2だが,PHP 5.1でも使えるとのことだ。
このファイルの冒頭には
#! /usr/bin/php -qC |
のようにphpコマンドへのパスが埋め込まれている。/usr/bin/以外のところにPHPをインストールしている場合はここを修正する。筆者はソースからPHPをインストールしているので,ここを
#! /usr/local/bin/php -qC |
と書き換えた。
pgfouineでは,グラフを描画するためにGDを使っており,PHPを作成する際にGDのサポートを有効にする必要がある。このため,PHP 4.4.2を作成する際に筆者は以下のようにconfigureのオプションを指定した。
# ./configure --without-mysql --with-apxs=/usr/local/apache/bin/apxs \ --enable-mbstring --enable-mbregex --with-pgsql --with-zlib \ --with-gd --with-jpeg-dir=/usr/lib --with-xpm-dir=/usr/lib \ --with-freetype-dir=/usr/lib --enable-gd-native-ttf --enable-gd-jis-conv |
pgFouineのオプション
pgFouineはPostgreSQLのログを解析,その結果をファイルに出力する。詳細はコマンドオプションで指定する。主なオプションを説明する。
表1●pgFouineのコマンド・オプション
-file |
解析対象のログファイル名。「-」を指定すると標準入力からログを読み込む。 |
-format |
出力フォーマット。text,html,html-with-graphs の中から選ぶ。省略すると html になる。 |
-report [outputfile=] |
出力ファイルをoutfileで指定する。block1,block2...はレポートのタイプであり,複数のレポートを同時に指定できる。レポートのタイプについては別途解説する。 |
-from " |
これより前の日付のログを無視する |
-to " |
これより後の日付のログを無視する |
pgFouineが解析できるログのフォーマット
pgFouineの解析できるログのフォーマットは今のところsyslogへの出力だけである。しかし,syslogへログを大量に出力すると,深刻なシステムのパフォーマンス低下をもたらす。そこで筆者はpgFouineにパッチを当て,ファイルへのログ出力をサポートできるようにした。
*** include/postgresql/parsers/SyslogPostgreSQLParser.class.php.orig 2006-04-16 22:01:41.000000000 +0900 --- include/postgresql/parsers/SyslogPostgreSQLParser.class.php 2006-04-01 23:09:07.000000000 +0900 *************** *** 25,31 **** var $regexpPostgresPid; function SyslogPostgreSQLParser($syslogString = 'postgres') { ! $this->regexpSyslogContext = new RegExp('/^([A-Z][a-z]{2} [ 0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}) .*? '.$syslogString.'\[(\d{1,5})\]: \[(\d{1,20})(?:\-(\d{1,5}))?\] /'); } function & parse($data) { --- 25,32 ---- var $regexpPostgresPid; function SyslogPostgreSQLParser($syslogString = 'postgres') { ! // $this->regexpSyslogContext = new RegExp('/^([A-Z][a-z]{2} [ 0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}) .*? '.$syslogString.'\[(\d{1,5})\]: \[(\d{1,20})(?:\-(\d{1,5}))?\] /'); ! $this->regexpSyslogContext = new RegExp('/^([0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2} JST) .*? '.$syslogString.'\[(\d{1,5})\]: \[(\d{1,10})(?:\-(\d{1,5}))?\] /'); } function & parse($data) { |
そして,postgresql.confを以下のように修正する(PostgreSQL 8.1の場合)。
log_destination = 'stderr' redirect_stderr = on log_duration = on log_statement = 'all' log_line_prefix = '%t myhost postgres[%p]: [%l-1] ' |
これで後はしばらくPostgreSQLを動かし,ログを収集する。