F.2. auto_explain

auto_explainモジュールは、手動でEXPLAINの実行を必要とせず、自動的に遅い文の実行計画をログ記録する手段を提供します。大きなアプリケーションにおける最適化されていない問い合わせを追跡するのに特に有用です。

このモジュールはSQLでアクセスできる関数を提供しません。使用するには、サーバに単に読み込ませます。ある個別のセッションに読み込ませることができます。

LOAD 'auto_explain';
  

(実行するためにはスーパーユーザでなければなりません。)より一般的な使用方法は、postgresql.confshared_preload_librariesauto_explainを含めて、すべてのセッションで事前にロードしておくことです。すると、想定外に低速な問い合わせを発生時に何も行うことなく追跡することができます。当然ながらこのためのオーバーヘッドという代償があります。

F.2.1. 設定パラメータ

auto_explainの動作を制御するいくつかの構成パラメータが存在します。デフォルトの動作は何もしないことなので、なんらかの結果を望むのであれば少なくともauto_explain.log_min_durationを設定しなければならないことに注意してください。

auto_explain.log_min_duration (integer)

auto_explain.log_min_durationは、文の実行計画がログに記録されるようになる、ミリ秒単位の最小の文実行時間です。これをゼロにすれば、すべての計画が記録されます。マイナス1(デフォルト)は計画の記録を無効にします。例えば、250msに設定すると、250ms以上実行する文すべてが記録されます。スーパーユーザのみがこの設定を変更することができます。

auto_explain.log_analyze (boolean)

auto_explain.log_analyzeは、実行計画のログが取得されたときに出力されるものとして、単にEXPLAIN出力ではなく、EXPLAIN ANALYZE出力を行います。このパラメータはデフォルトで無効です。スーパユーザのみ、この設定を変更できます。

注意: このパラメータが有効の場合、計画ノードごとの時間的調整は事実上ログされるまで如何に時間が掛かろうと、全ての実行文に対して引き起こります。極端に性能上のマイナスの影響が起こり得ます。

auto_explain.log_verbose (boolean)

auto_explain.log_verboseは、実行計画のログが取得されたときに出力されるものとして、単にEXPLAIN出力ではなく、EXPLAIN VERBOSE出力を行います。このパラメータはデフォルトで無効です。スーパユーザのみ、この設定を変更できます。

auto_explain.log_nested_statements (boolean)

auto_explain.log_nested_statementsにより、入れ子状の文(関数内から実行される文)を考慮して記録するようになります。無効ならば、最上位の問い合わせ計画のみが記録されます。このパラメータはデフォルトで無効です。スーパーユーザのみがこの設定を変更することができます。

これらパラメータをpostgresql.confファイルに設定するためには、custom_variable_classesauto_explainを追加する必要があります。典型的な使用法は以下のようになります。

# postgresql.conf
shared_preload_libraries = 'auto_explain'

custom_variable_classes = 'auto_explain'
auto_explain.log_min_duration = '3s'
  

F.2.2. 例

  postgres=# LOAD 'auto_explain';
  postgres=# SET auto_explain.log_min_duration = 0;
  postgres=# SELECT count(*)
               FROM pg_class, pg_index
              WHERE oid = indrelid AND indisunique;
  

これにより、以下のようなログ出力が作成されます。

  LOG:  duration: 0.986 ms  plan:
          Aggregate  (cost=14.90..14.91 rows=1 width=0)
            ->  Hash Join  (cost=3.91..14.70 rows=81 width=0)
                  Hash Cond: (pg_class.oid = pg_index.indrelid)
                  ->  Seq Scan on pg_class  (cost=0.00..8.27 rows=227 width=4)
                  ->  Hash  (cost=2.90..2.90 rows=81 width=4)
                        ->  Seq Scan on pg_index  (cost=0.00..2.90 rows=81 width=4)
                              Filter: indisunique
  STATEMENT:  SELECT count(*)
            FROM pg_class, pg_index
           WHERE oid = indrelid AND indisunique;
  

F.2.3. 作者

板垣 貴裕