2012年12月5日

PostgreSQL版topコマンド「pg_top」を使ってみよう

PostgreSQL Advent Calendar 2012(全部俺)のDay 5です。

Unix系プラットフォームでシステムの開発または管理をしている方は、topというコマンドをご存じだと思います。システムのロードアベレージを見たり、実行中の各プロセスの負荷を見たりするアレですね。

実は、PostgreSQLにも "pg_top" という似たような機能を実現するユーティリティがあります。今回はその使い方を簡単に御紹介します。

■pg_topとは


pg_topはPostgreSQL関連の開発をしているMark Wong氏によって開発されたツールです。

PostgreSQL top (pg_top): Project Home Page
http://ptop.projects.pgfoundry.org/

もともとはpgFoundryでホストされたプロジェクトでしたが、ソースコードの最新版は現在はGitHubにあるようです。

markwkm/pg_top
https://github.com/markwkm/pg_top

■pg_topのコンパイルとインストール


GitHub上では最新バージョンのtarballはまだリリースされていないようなので、リポジトリのHEADから最新版を取得します。

以下のページから「Download as tar.gz」を選択して、HEADに含まれるソースコード一式をtar.gz形式でダウンロードします。

https://github.com/markwkm/pg_top/downloads

Firefoxの場合は拡張子がtar.gzになりましたが、wgetでダウンロードすると拡張子無しでダウンロードされてしまうようなので、必要に応じて拡張子をtar.gzに変更してソースコードを展開します。
[snaga@devsv02 pg_top]$ wget --no-check-certificate https://github.com/markwkm/pg_top/archive/master.tar.gz
--2012-11-24 14:51:03--  https://github.com/markwkm/pg_top/archive/master.tar.gz
Resolving github.com... 207.97.227.239
Connecting to github.com|207.97.227.239|:443... connected.
(...snip...)
HTTP request sent, awaiting response... 200 OK
Length: 208154 (203K) [application/x-gzip]
Saving to: `master'

100%[======================================>] 208,154      176K/s   in 1.2s

2012-11-24 14:51:06 (176 KB/s) - `master' saved [208154/208154]

[snaga@devsv02 pg_top]$ ls -l master
-rw-rw-r-- 1 snaga snaga 208154 Nov 24 14:51 master
[snaga@devsv02 pg_top]$ file master
master: gzip compressed data, from Unix
[snaga@devsv02 pg_top]$ mv master master.tar.gz
[snaga@devsv02 pg_top]$ tar zxf master.tar.gz
[snaga@devsv02 pg_top]$ cd pg_top-master/
[snaga@devsv02 pg_top-master]$ ls
autogen.sh*    config.sub*    INSTALL      os.h         Porting      username.c
boolean.h      configure.ac*  layout.h     pg.c         README       username.h
c.h            display.c      LICENSE      pg.h         remote.h     utils.c
color.c        display.h      loadavg.h    pg_top.1.in  screen.c     utils.h
color.h        FAQ            machine/     pg_top.c     screen.h     version.c
commands.c     getopt.c       machine.h    pg_top.h     sigconv.awk  version.h
commands.h     help.h         Makefile.am  pg_trace.h   sprompt.c    Y2K
config.guess*  HISTORY        message.h    port.h       TODO
[snaga@devsv02 pg_top-master]$
ソースコードを展開したら、autogen.shを実行してconfigureスクリプトを作成します。
[snaga@devsv02 pg_top-master]$ ./autogen.sh
configure.ac: installing `./install-sh'
configure.ac: installing `./missing'
Makefile.am: installing `./depcomp'
[snaga@devsv02 pg_top-master]$ 
configureスクリプトができたら、--with-postgresqlオプションにPostgreSQLのインストールディレクトリを指定して、configureスクリプトを実行します。
[snaga@devsv02 pg_top-master]$ ./configure --with-postgresql=/usr/pgsql-9.1
Configuring pg_top 3.7.0-alpha1
checking build system type... x86_64-unknown-linux-gnu
checking host system type... x86_64-unknown-linux-gnu
checking target system type... x86_64-unknown-linux-gnu
(...snip...)
checking for pg_config... /usr/pgsql-9.1/bin/pg_config
checking for PostgreSQL libraries... checking for library containing kstat_open... no
(...snip...)
configure: creating ./config.status
config.status: creating Makefile
config.status: creating pg_top.1
config.status: creating config.h
config.status: executing depfiles commands
[snaga@devsv02 pg_top-master]$
Makefileが作成されたら、内部のLIBS変数に "-lpq" を追加するように修正します。これを追加しないと、makeの時にundefined referenceエラーが出てビルドできません。
LIBS = -ldl -lm -ltermcap -lelf -lpq
最後にmakeを叩いてコンパイルは完了です。
[snaga@devsv02 pg_top-master]$ make
gawk -f ./sigconv.awk /usr/include/bits/signum.h > sigdesc.h
make  all-am
make[1]: Entering directory `/home/snaga/pgsql/pg_top/pg_top-master'
if gcc -DHAVE_CONFIG_H -I. -I. -I.  -I/usr/pgsql-9.1/include   -Wall -g -MT color.o -MD -MP -MF ".deps/color.Tpo" -c -o color.o color.c; \
        then mv -f ".deps/color.Tpo" ".deps/color.Po"; else rm -f ".deps/color.Tpo"; exit 1; fi
(...snip...)
gcc  -Wall -g -L/usr/pgsql-9.1/lib  -o pg_top  color.o commands.o display.o getopt.o screen.o sprompt.o pg.o pg_top.o username.o utils.o version.o m_remote.o m_linux.o -ldl -lm -ltermcap -lelf -lpq
make[1]: Leaving directory `/home/snaga/pgsql/pg_top/pg_top-master'
[snaga@devsv02 pg_top-master]$ ls -l pg_top
-rwxrwxr-x 1 snaga snaga 201257 Nov 24 15:01 pg_top*
[snaga@devsv02 pg_top-master]$

■pg_topを使ってみる


それでは、さっそくpg_topを使ってみましょう。
[snaga@devsv02 pg_top-master]$ ./pg_top -h
./pg_top: option requires an argument -- h
pg_top version 3.7.0-alpha1
Usage: pg_top [-ITWbcinqru] [-x x] [-s x] [-o field] [-z username]
          [-p PORT] [-U USER] [-d DBNAME] [-h HOSTNAME] [number]
[snaga@devsv02 pg_top-master]$
上記の通り、pg_topにはいろいろなオプションがありますが、まずは-dオプションでデータベース名だけを指定して起動してみます。
[snaga@devsv02 pg_top-master]$ ./pg_top -d pgbench
すると以下のような画面が表示されます。



ここで負荷をかけ始めると、複数のバックエンドプロセスが表示されます。


■ロックの状態を見てみる


各プロセスの取得しているロックの状態を見てみましょう。

プロセス一覧が表示されている状態で 'L' キーを押します。すると、"Show locks held by process: " というプロンプトが出ますのでプロセスIDを入力してENTERを押します。



すると、指定したプロセスが取得しているロックについて、テーブル、ロック種別、およびロックの獲得状態の一覧を表示してくれます。


■テーブル/インデックスのアクセス統計情報を見てみる


次に、テーブルやインデックスのアクセス統計情報を見てみます。

プロセス一覧の画面で 'R' キーを押すと、テーブルのアクセス統計情報が表示されます。


  • SEQ_SCANS シーケンシャルスキャンの回数
  • SEQ_READS シーケンシャルスキャン経由で読み出されたレコード数
  • I_SCANS インデックススキャンの回数
  • I_FETCHES インデックススキャン経由で読み出されたレコード数
  • INSERTS INSERTの回数
  • UPDATES UPDATEの回数
  • DELETES DELETEの回数
  • RELNAME テーブル名

ここで表示されている数値は、前回表示して以降どれくらいアクセスがあったかを示す「差分」の数値になります。差分ではなく、過去のアクセスすべてを積算した値が欲しい場合には、't' キーで切り替えることができます。

't' キーを押して、"Displaying cumulative statistics." と出たら積算値の表示で、"Displaying differential statistics." と出たら差分値の表示を示しています。



差分データに戻す場合は再度 't' で切り替えます。

インデックスの統計情報を表示するには、'X' キーをクリックします。


■実行中のクエリのEXPLAINを見る


pg_topでは、指定したプロセスが実行しているクエリの実行プランを表示してくれる、という機能があります。実行に長時間かかっているクエリの内容を見る場合に便利です。

'E' キーを押してバックエンドのプロセスIDを入力すると、実行中のSQLのEXPLAINを表示してくれます。




但し、バージョン9.1以前でこの機能を使う場合にはバグがありましたので、以下のように pg.c を修正してからコンパイルする必要があります。(Mark Wong氏にはpull requestを送ったので、もしかしたらエントリ公開までにfixされているかもしれません11/30時点でMark Wong氏のレポジトリにマージされました
*** pg.c.orig   2012-10-20 09:23:22.000000000 +0900
 --- pg.c        2012-11-24 15:50:12.000000000 +0900
***************
*** 22,28 ****
                "WHERE pid = %d;"

  #define CURRENT_QUERY_9_1 \
!               "SELECT query\n" \
                "FROM pg_stat_activity\n" \
                "WHERE procpid = %d;"

--- 22,28 ----
                "WHERE pid = %d;"

  #define CURRENT_QUERY_9_1 \
!               "SELECT current_query\n" \
                "FROM pg_stat_activity\n" \
                "WHERE procpid = %d;"

■まとめ


今回は、Unix系ではお馴染みのtopコマンドと類似のツールであるpg_topを紹介しました。

データベースのパフォーマンスを分析するには、さまざまな要素が関連しているため、ツールの支援を得ることが極めて重要だと思います。このようなツールも使ってサクサクと問題の絞り込みをしていただければと思います。

ではでは。

0 件のコメント:

コメントを投稿