統計情報コレクタ

PostgreSQL 9.0.0文書
前のページ | 巻戻し | 第 27章データベース活動状況の監視 | 早送り | 次のページ

# 27.2. 統計情報コレクタ

PostgreSQLの統計情報コレクタはサーバの活動状況に関する情報を収集し、報告するサブシステムです。 現在、コレクタはテーブルとインデックスへのアクセスをディスクブロックおよび個々の行単位で数えることができます。 またこれは、各テーブル内の総行数、および、各テーブルで最後にバキュームした時刻、最後に解析した時刻を追跡します。 また、ユーザ定義関数の呼ばれた回数、それぞれの消費した総時間をカウントします。

また、PostgreSQLは他のサーバプロセスによって現在実行されている問い合わせを正確に報告する機能を持ちます。 これはコレクタプロセスから独立している機能です。

## 27.2.1. 統計情報収集のための設定

統計情報の収集によって問い合わせの実行に少しオーバーヘッドが加わりますので、システムは情報を収集するようにもしないようにも設定することができます。 これは通常は`postgresql.conf`内で設定される、設定パラメータによって制御されます （設定パラメータの設定についての詳細は第18章を参照してください）。

track_countsパラメータは、テーブルおよびインデックスアクセスに関する統計情報を収集するかどうか制御します。

track_functionsパラメータは、ユーザ定義関数の使用状況を追跡するかどうかを指定できます。

track_activitiesパラメータにより、すべてのサーバプロセスで現在実行されているコマンドを監視することができます。

通常、これらの変数は全てのサーバプロセスに適用できるように`postgresql.conf`内で設定されます。 しかし、SETコマンドを使用して、個別のセッションで有効または無効にすることができます （一般ユーザがその活動を管理者に隠すことを防止するために、スーパーユーザのみが`SET`を使用してこれらのパラメータを変更することができます。）

統計情報コレクタはバックエンドと必要な情報(自動バキュームに関するものも含む)のやり取りを、一時ファイルを通じて行います。これらのファイルは`pg_stat_tmp`サブディレクトリに格納されます。 postmasterがシャットダウンした際は、統計情報データの永続的なコピーが`global`サブディレクトリに格納されます。性能向上のため、stats_temp_directoryパラメータでRAMベースのファイルシステムを指定することで、物理I/Oの要求を減らすことができます。

## 27.2.2. 収集した統計情報の表示

統計情報の収集結果を表示するための、多くの定義済みのビューがあり、表27-1に一覧表示されています。 他にも、基礎的な統計情報関数を使用した独自のビューを構築することもできます。

この統計情報を使用して、現在の活動状況を監視する場合、この情報は即座に更新されないことを認識することが重要です。 個別のサーバプロセスは、待機状態になる直前に、新しい統計情報に関する数をコレクタに送信します。 ですので、実行中の問い合わせやトランザクションは表示上の総和には影響を与えません。 また、コレクタ自体もおよそ`PGSTAT_STAT_INTERVAL`（サーバ構築時に変更しない限り500）ミリ秒に一度新しい報告を出力します。 ですので、表示上の情報は実際の活動から遅れて表示されます。 しかし、`track_activities`で収集される現在の問い合わせの情報は常に最新です。

この他の重要なポイントは、いつサーバプロセスが統計情報を表示するように尋ねられるかです。 サーバプロセスは、まずコレクタによって発行された最も最近の報告を取り出します。 そして、現在のトランザクションが終わるまで、全ての統計情報ビューと関数においてこのスナップショットを使用し続けます。 ですから、現在のトランザクションを続けている間、統計情報は一定の情報を示します。 同様に、全セッションの現在の問い合わせに関する情報も、そうした情報がトランザクションで最初に要求された時に収集され、そのトランザクションの間同じ情報が表示されます。 これはバグではなく、特徴です。 なぜなら、これにより、知らない間に値が変更することを考慮することなく、統計情報に対して複数の問い合わせを実行し、その結果を相関することができるからです。 しかし、各問い合わせで新しい結果を取り出したい場合は、確実にトランザクションブロックの外側でその問い合わせを行ってください。 他にも`pg_stat_clear_snapshot`()を呼び出すこともできます。 これは現在のトランザクションの統計情報スナップショットを（もしあれば）破棄します。 次に統計情報を使用する場合に新しいスナップショットを取り出すことになります。

表 27-1. 標準統計情報ビュー

ビュー名 | 説明
--- | ---
`pg_stat_activity` | サーバプロセス当たり1行の形で、データベースのOID、データベース名、プロセスID、ユーザのOID、ユーザ名、アプリケーション名、クライアントアドレスとポート番号、サーバプロセスの開始時刻、現在のトランザクションの開始時刻、現在の問い合わせの実行開始時刻、プロセスの待機状態、そして現在の問い合わせのテキストを表示します。 現在の問い合わせについてのデータを報告する列は`track_activities`パラメータが有効な場合に表示されます。 さらに、その列は、ビューを確認するユーザがスーパーユーザ、あるいは報告対象プロセスを所有するユーザと同じである場合にのみ参照可能です。
`pg_stat_bgwriter` | バックグランドライタによるクラスタ全体の統計情報、つまり、予定されるチェックポイント数、要求されるチェックポイント数、チェックポイントおよび整理用スキャンで書き込みされるバッファ数、およびあまりに多くのバッファを書き出したために整理用スキャンを中断したバックグランドライタの個数を、1行のみ表示します。 また、バックエンド（つまりバックグランドライタによるものではない）により書き込まれたバッファと割り当てられたバッファ全体を含む、共有バッファプールに関する統計情報も含まれます。
`pg_stat_database` | データベース当たり1行の形で、データベースのOID、データベース名、そのデータベースに接続する活動中のサーバプロセス数、そのデータベース中でコミットされたトランザクションの総数、ロールバックされたトランザクションの総数、読み取られたディスクブロックの総数、バッファヒット（つまり、バッファキャッシュに対象とするブロックが存在するために防止されたブロック読み取り要求）の総数、抽出・挿入・更新・削除により返された行数を表示します。
`pg_stat_all_tables` | 現在のデータベース内の各テーブル（TOASTテーブルを含みます）に関する、テーブルのOID、スキーマおよびテーブル名、開始されたシーケンシャルスキャン数、シーケンシャルスキャンで取り出された実際の行数、（そのテーブルに属するすべてのインデックスに対して）開始されたインデックススキャン数、インデックススキャンで取り出された実際の行数、挿入、更新、削除された行数、HOT（つまり分離したインデックス更新がない）だった更新行の数、有効行数、無効行数、手作業によってそのテーブルがバキュームされた前回の時刻、自動バキュームデーモンによりバキュームされた前回の時刻、手作業によって解析された前回の時刻、自動バキュームデーモンにより解析された前回の時刻。
`pg_stat_sys_tables` | システムテーブルのみが表示される点を除き、`pg_stat_all_tables`と同じです。
`pg_stat_user_tables` | ユーザテーブルのみが表示される点を除き、`pg_stat_all_tables`と同じです。
`pg_stat_all_indexes` | 現在のデータベース内の各インデックスに関する、テーブルとインデックスのOID、スキーマ、テーブルとインデックスの名前、開始されたインデックススキャン数、インデックススキャンによって読み取られたインデックス項目数、インデックスを使用した単純なインデックススキャンで取り出された実際のテーブル行の数。
`pg_stat_sys_indexes` | システムテーブルのインデックスのみが表示される点を除き、`pg_stat_all_indexes`と同じです。
`pg_stat_user_indexes` | ユーザテーブルのインデックスのみが表示される点を除き、`pg_stat_all_indexes`と同じです。
`pg_statio_all_tables` | 現在のデータベース内の各テーブル（TOASTテーブルを含みます）に関する、テーブルのOID、スキーマとテーブル名、そのテーブルから読み取られたディスクブロックの総数、バッファヒット数、そのテーブルに関する全てのインデックスから読み取られたディスクブロック数とバッファヒット数、（存在する場合）そのテーブルの補助的なTOASTテーブルから読み取られたディスクブロック数とバッファヒット数、TOASTテーブルのインデックスから読み取られたディスクブロック数とバッファヒット数。
`pg_statio_sys_tables` | システムテーブルのみが表示される点を除き、`pg_statio_all_tables`と同じです。
`pg_statio_user_tables` | ユーザテーブルのみが表示される点を除き、`pg_statio_all_tables`と同じです。
`pg_statio_all_indexes` | 現在のデータベース内の各インデックスに関する、テーブルとインデックスのOID、スキーマ、テーブルおよびインデックスの名前、そのインデックスから読み取られたディスクブロック数とバッファヒット数。
`pg_statio_sys_indexes` | システムテーブルのインデックスのみが表示される点を除き、`pg_statio_all_indexes` と同じです。
`pg_statio_user_indexes` | ユーザテーブルのインデックスのみが表示される点を除き、`pg_statio_all_indexes`と同じです。
`pg_statio_all_sequences` | 現在のデータベース内の各シーケンスオブジェクトに関する、シーケンスのOID、スキーマとシーケンスの名前、そのシーケンスから読み取られたディスクブロック数とバッファヒット数。
`pg_statio_sys_sequences` | システムシーケンスのみが表示される点を除き、`pg_statio_all_sequences`と同じです （現時点では、システムシーケンスは定義されていませんので、このビューは常に空です）。
`pg_statio_user_sequences` | ユーザシーケンスのみが表示される点を除き、`pg_statio_all_sequences`と同じです。
`pg_stat_user_functions` | 追跡された全ての関数に関する、関数のOID、スキーマ、関数名、呼ばれた回数、総処理時間、関数自身のみの処理時間。 関数自身の処理時間とは、関数自身が消費した総時間であり、総処理時間とは関数内で呼ばれている別の関数の消費時もを含めたものです。 時間の単位はミリ秒です。

インデックス単位の統計情報は、どのインデックスが使用され、どの程度効果があるのかを評価する際に、特に有用です。

PostgreSQL 8.1から、インデックスを直接的、または"ビットマップスキャン"経由で使用することができます。 ビットマップスキャンでは、複数のインデックスの出力をANDまたはOR規則を使って組み合わせることができます。 そのため、ビットマップスキャンが使用されると、個々のヒープ行の取り出しと特定のインデックスとを関連付けることは困難です。 したがって、ビットマップスキャンは使用したインデックスに関する`pg_stat_all_indexes`.`idx_tup_read`の数を増やします。 さらに、そのテーブルに関する`pg_stat_all_tables`.`idx_tup_fetch`の数も増やします。 しかし、`pg_stat_all_indexes`.`idx_tup_fetch`を変更しません。

> 注意: PostgreSQL 8.1より前では、`idx_tup_read` の値と`idx_tup_fetch`の値は基本的には常に同じでした。 `idx_tup_read`はインデックスから取り出したインデックス項目数を数え、一方で`idx_tup_fetch`はテーブルから取り出した有効な行数を数えますので、ビットマップスキャンを考慮しなくても、この2つの値が異なることがあり得るようになりました。 インデックスを使用して取り出した行に無効または未コミットの行があると、後者は少なくなります。

`pg_statio_`ビューは主に、バッファキャッシュの効率を評価する際に有用です。 実ディスク読み取りの数がバッファヒットの数よりもかなり少ないのであれば、そのキャッシュはカーネル呼び出しを行うことなく、ほとんどの読み取り要求を満足させています。 しかし、PostgreSQLバッファキャッシュに存在しないデータはカーネルのI/Oキャッシュにある可能性があり、そのため、物理的な読み取りを行うことなく取り出される可能性があるというPostgreSQLのディスクI/Oの取り扱いのため、これらの統計情報は、完全な論拠を提供しません。 PostgreSQLのI/O動作に関するより詳細な情報を入手したいのであれば、PostgreSQL統計情報コレクタとカーネルのI/Oの取り扱いの監視を行うオペレーティングシステムユーティリティを組み合わせることを勧めます。

統計情報を参照する他の方法は、上述の標準ビュー同様に、基礎的な統計情報アクセス関数を使用した問い合わせを作成することで設定することができます。 これらの関数は表27-2にリストされています。データベースごとのアクセス関数は、どのデータベースに対して報告するのかを識別するためにデータベースのOIDを受け付けます。 テーブルごと、インデックスごとの関数はテーブルの、もしくはインデックスのOIDを受け付けます。 関数呼び出しに関する統計情報の関数は、関数のOIDを受け付けます。（この関数を使用して参照できるテーブルとインデックス、及び関数は現在のデータベース内のものだけであることに注意してください）。 サーバプロセスごとのアクセス関数はサーバプロセスID番号を受け付けます。 取り得る範囲は1から現時点で活動中のサーバプロセスの数までです。

表 27-2. 統計情報アクセス関数

関数 | 戻り値の型 | 説明
--- | --- | ---
``pg_stat_get_db_numbackends`(`oid`)` | `integer` | データベース内で活動中のサーバ数。
``pg_stat_get_db_xact_commit`(`oid`)` | `bigint` | データベース内でコミットされたトランザクション数。
``pg_stat_get_db_xact_rollback`(`oid`)` | `bigint` | データベース内でロールバックされたトランザクション数。
``pg_stat_get_db_blocks_fetched`(`oid`)` | `bigint` | データベースに関する、ディスクブロック抽出要求数。
``pg_stat_get_db_blocks_hit`(`oid`)` | `bigint` | データベースに関する、ディスクブロック要求の内キャッシュに存在した数。
``pg_stat_get_db_tuples_returned`(`oid`)` | `bigint` | データベースに関する、返されるタプル数。
``pg_stat_get_db_tuples_fetched`(`oid`)` | `bigint` | データベースに関する、抽出されるタプル数。
``pg_stat_get_db_tuples_inserted`(`oid`)` | `bigint` | データベースに関する、挿入されるタプル数。
``pg_stat_get_db_tuples_updated`(`oid`)` | `bigint` | データベースに関する、更新されるタプル数。
``pg_stat_get_db_tuples_deleted`(`oid`)` | `bigint` | データベースに関する、削除されるタプル数。
``pg_stat_get_numscans`(`oid`)` | `bigint` | 引数がテーブルの場合、シーケンシャルスキャンの実行回数。 引数がインデックスの場合インデックススキャンの実行回数。
``pg_stat_get_tuples_returned`(`oid`)` | `bigint` | 引数がテーブルの場合、シーケンシャルスキャンによって読み取られた行数。 引数がインデックスの場合、返されたインデックス項目数。
``pg_stat_get_tuples_fetched`(`oid`)` | `bigint` | 引数がテーブルの場合、ビットマップスキャンで抽出されたテーブル行の数。 引数がインデックスの場合、このインデックスを使用した単純なインデックススキャンで抽出された、テーブル行の数。
``pg_stat_get_tuples_inserted`(`oid`)` | `bigint` | テーブルに挿入された行数。
``pg_stat_get_tuples_updated`(`oid`)` | `bigint` | テーブルで更新された行数（HOT更新を含む）。
``pg_stat_get_tuples_deleted`(`oid`)` | `bigint` | テーブルで削除された行数。
``pg_stat_get_tuples_hot_updated`(`oid`)` | `bigint` | テーブルでHOT更新された行数。
``pg_stat_get_live_tuples`(`oid`)` | `bigint` | テーブル内の有効行数。
``pg_stat_get_dead_tuples`(`oid`)` | `bigint` | テーブル内の無効行数。
``pg_stat_get_blocks_fetched`(`oid`)` | `bigint` | テーブルまたはインデックスに関する、ディスクブロック抽出要求数。
``pg_stat_get_blocks_hit`(`oid`)` | `bigint` | テーブルまたはインデックスに関する、ディスクブロック抽出要求の内キャッシュ内に存在した数。
``pg_stat_get_last_vacuum_time`(`oid`)` | `timestamptz` | テーブルに対してユーザが行ったバキュームの最終時刻。
``pg_stat_get_last_autovacuum_time`(`oid`)` | `timestamptz` | テーブルに対して自動バキュームデーモンが行ったバキュームの最終時刻。
``pg_stat_get_last_analyze_time`(`oid`)` | `timestamptz` | テーブルに対してユーザが行った解析の最終時刻。
``pg_stat_get_last_autoanalyze_time`(`oid`)` | `timestamptz` | テーブルに対して自動バキュームデーモンが行った解析の最終時刻。
``pg_backend_pid()`` | `integer` | 現在のセッションに接続するサーバプロセスのプロセスID。
``pg_stat_get_activity`(`integer`)` | `setof record` | PIDが指定された場合、それに該当するバックエンドの情報のレコード、`NULL`が指定された場合はシステム上のアクティブな各バックエンドの情報がレコードが返されます。返される情報内容は`pg_stat_activity`の一部と同じです。
``pg_stat_get_function_calls`(`oid`)` | `bigint` | 関数が呼ばれた回数。
``pg_stat_get_function_time`(`oid`)` | `bigint` | 関数内で消費された時間(マイクロ秒)です。この関数で呼ばれた別の関数の消費時間も含まれています。
``pg_stat_get_function_self_time`(`oid`)` | `bigint` | この関数のみで消費された時間です。この関数から呼ばれた別の関数の消費時間は含まれていません。
``pg_stat_get_backend_idset()`` | `setof integer` | 現在活動中のサーバプロセス数のセット（1から活動中のサーバプロセス数までの間）。 以下の使用例を参照してください。
``pg_stat_get_backend_pid`(`integer`)` | `integer` | 指定されたサーバプロセスのプロセスID。
``pg_stat_get_backend_dbid`(`integer`)` | `oid` | 指定されたサーバプロセスのデータベースID。
``pg_stat_get_backend_userid`(`integer`)` | `oid` | 指定されたサーバプロセスのユーザID。
``pg_stat_get_backend_activity`(`integer`)` | `text` | 指定されたサーバプロセスの現在の問い合わせ。 ただし、現在のユーザがスーパーユーザの場合、または問い合わせ先セッションのユーザの同一の場合（かつ、`track_activities`が有効の場合）のみです。
``pg_stat_get_backend_waiting`(`integer`)` | `boolean` | 指定されたサーバプロセスがロック待ち状態の場合に真です。 しかし、現在のユーザがスーパーユーザの場合、または、問い合わせを行ったユーザと同一の場合（かつ、`track_activities`が有効の場合）に限ります。
``pg_stat_get_backend_activity_start`(`integer`)` | `timestamp with time zone` | 指定されたサーバプロセスが実行中の問い合わせを開始した時刻。 ただし、現在のユーザがスーパーユーザの場合、または問い合わせ先セッションのユーザの同一の場合（かつ、`track_activities`が有効の場合）のみです。
``pg_stat_get_backend_xact_start`(`integer`)` | `timestamp with time zone` | 指定したサーバプロセスで現在実行中のトランザクションが始まった時刻。 ただし、現在のユーザがスーパーユーザの場合、または問い合わせ先セッションのユーザの同一の場合（かつ、`track_activities`が有効の場合）のみです。
``pg_stat_get_backend_start`(`integer`)` | `timestamp with time zone` | 指定されたサーバプロセスが開始した時刻。 現在のユーザがスーパーユーザまたは問い合わせを行っているセッションユーザと同じでない場合はNULL。
``pg_stat_get_backend_client_addr`(`integer`)` | `inet` | 指定されたサーバプロセスに接続するクライアントのIPアドレス。 Unixドメインソケット経由の接続の場合はNULL。 また、現在のユーザがスーパーユーザまたは問い合わせを行っているセッションユーザと同じでない場合もNULL。
``pg_stat_get_backend_client_port`(`integer`)` | `integer` | 指定されたサーバプロセスに接続するクライアントのTCPポート番号。 Unixドメインソケット経由の接続の場合は-1。 現在のユーザがスーパーユーザまたは問い合わせを行っているセッションユーザと同じでない場合はNULL。
``pg_stat_get_bgwriter_timed_checkpoints()`` | `bigint` | （`checkpoint_timeout`時間経過したために）バックグランドライタが予定されたチェックポイントを起動した回数。
``pg_stat_get_bgwriter_requested_checkpoints()`` | `bigint` | `checkpoint_segments`を超えた、あるいは`CHECKPOINT`が呼び出されたという理由によりバックエンドからの要求に基づき、バックグランドライタがチェックポイントを起動した回数。
``pg_stat_get_bgwriter_buf_written_checkpoints()`` | `bigint` | バックグランドライタがチェックポイント期間中に書き込んだバッファ数。
``pg_stat_get_bgwriter_buf_written_clean()`` | `bigint` | ダーティページの書き出し処理のためにバックグランドライタが書き出したバッファ数。
``pg_stat_get_bgwriter_maxwritten_clean()`` | `bigint` | バッファへの書き出しが`bgwriter_lru_maxpages`パラメータで指定した数以上発生したためにバックグランドライタが書き出し用スキャンを中断した回数。
``pg_stat_get_buf_written_backend()`` | `bigint` | 新しいバッファ割り当てを行う必要があったためにバックエンドにより書き込まれたバッファ数。
``pg_stat_get_buf_alloc()`` | `bigint` | 割り当てられたバッファの総数。
``pg_stat_clear_snapshot()`` | `void` | 現在の統計情報スナップショットを破棄します。
``pg_stat_reset()`` | `void` | 現在のデータベースに関する統計カウンタすべてをゼロにリセットします（スーパーユーザ権限が必要です）。
``pg_stat_reset_shared`(text)` | `void` | データベースクラスタの共有統計情報カウンタの一部をゼロに戻します（スーパーユーザ権限が必要です）。`pg_stat_reset_shared('bgwriter')`を呼び出すと、`pg_stat_bgwriter`で示される値すべてがゼロになります。
``pg_stat_reset_single_table_counters`(oid)` | `void` | 現在のデータベース内にある、ひとつのテーブルあるいはインデックスの統計情報をゼロにリセットします（スーパーユーザ権限が必要です）。
``pg_stat_reset_single_function_counters`(oid)` | `void` | 現在のデータベース内にある、ひとつの関数の統計情報をゼロにリセットします（スーパーユーザ権限が必要です）。

> 注意: `pg_stat_get_blocks_fetched`から`pg_stat_get_blocks_hit`を引くと、そのテーブル、インデックス、データベースに対して発行されたカーネルの`read()`コール数がわかります。実際の物理的な読み取り数は、カーネルレベルのバッファ処理のために通常これより小さくなります。`*_blks_read`の統計情報カラムはfetched数からhit数を差し引いた結果を用いています。

バックエンドに関する情報にアクセスする関数は、全てバックエンドのIDでインデックス化されています。ただし、`pg_stat_get_activity`だけはPIDでインデックス化されています。`pg_stat_get_backend_idset`関数は、活動中のサーバプロセスそれぞれについて1行を作成する簡便な方法を提供します。例えば、全てのサーバプロセスのPIDと現在の問い合わせを表示するには、以下を行います。

    SELECT pg_stat_get_backend_pid(s.backendid) AS procpid,
           pg_stat_get_backend_activity(s.backendid) AS current_query
        FROM (SELECT pg_stat_get_backend_idset() AS backendid) AS s;

前のページ | ホーム | 次のページ
標準的なUnixツール | 上に戻る | ロックの表示