F.3. auto_explain

auto_explain模块自动提供一种慢语句记录执行计划的方法 没有手动运行EXPLAIN。 这对于在大型应用程序中跟踪未优化查询尤其有用。

该模块没有提供SQL访问函数。为了使用它,简单加载它到服务器中。 你可以加载它到独立会话中:

LOAD 'auto_explain';

(你一定是超级用户才能这样做。) 更典型的用法是预先加载它到 在postgresql.confsession_preload_librariesshared_preload_libraries中 包含auto_explain的一些或者所有会话。然后, 你可以出乎意料地跟踪无论什么时候会发生的慢查询。 当然有价值开销。

F.3.1. 配置参数

有几个配置参数控制auto_explain的操作。注意, 缺省操作是什么也不做,如果你想要任何结果, 那么你必须至少设置auto_explain.log_min_duration

auto_explain.log_min_duration (integer)

auto_explain.log_min_duration是最小声明执行时间, 以毫秒为单位,将导致语句的计划被记录。设置它为零记录所有计划。 减一(缺省)禁止计划的记录。比如,如果你设置它为250ms, 那么运行250ms或者更长时间的所有语句将被记录。只有超级用户可以改变这个设置。

auto_explain.log_analyze (boolean)

auto_explain.log_analyze导致EXPLAIN ANALYZE 输出,而不是EXPLAIN输出,当记录一个执行计划时,被打印。 该参数缺省是关闭的。只有超级用户可以改变这个设置。

注意: 当该参数打开时,为所有执行语句产生每个计划节点时间, 无论他们是否运行足够长的时间来获得记录。 这会对性能产生极其不利的影响。关闭auto_explain.log_timing 改善性能成本,代价是获取较少的信息。

auto_explain.log_buffers (boolean)

auto_explain.log_buffers控制记录一个执行计划时, 是否输出缓存使用状态;它相当于EXPLAINBUFFERS选项。 该参数不起作用除非启用了auto_explain.log_analyze。 该参数缺省是关闭的。只有超级用户可以改变这个设置。

auto_explain.log_timing (boolean)

auto_explain.log_timing控制记录执行计划时, 是否输出每节点的时间信息;它相当于EXPLAINTIMING 选项。反复读取系统时钟的开销可以显著减缓一些系统上的查询, 因此当计算实际行时,设置该参数为关闭是非常有用的,不需要确切时间。 当启动auto_explain.log_analyze时,该参数是有效的。 缺省该参数是打开的。只有超级用户可以改变该设置。

auto_explain.log_triggers (boolean)

auto_explain.log_triggers导致记录执行计划时包括触发器执行统计。 这个参数没什么影响,除非启用了auto_explain.log_analyze。 该参数缺省是关闭的。只有超级用户可以改变这个设置。

auto_explain.log_verbose (boolean)

auto_explain.log_verbose控制记录日志文件时, 是否输出详细的细节;它相当于EXPLAINVERBOSE 选项。只有超级用户可以改变这个设置。

auto_explain.log_format (enum)

auto_explain.log_format选择使用 EXPLAIN输出格式。 允许值是text,xml, jsonyaml。 缺省是text。只有超级用户可以改变这个设置。

auto_explain.log_nested_statements (boolean)

auto_explain.log_nested_statements为了记录导致嵌套语句(语句在函数内执行)。 当它是关闭时,只记录顶级查询计划。 该参数缺省是关闭的。 只有超级用户可以改变这个设置。

在普通使用中,在postgresql.conf中设置这些参数, 尽管超级用户可以在他们自己的会话中在运行时修改它们。典型的用法是:

# postgresql.conf
session_preload_libraries = 'auto_explain'

auto_explain.log_min_duration = '3s'

F.3.2. 例子

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

这可能产生日志输出比如:

LOG:  duration: 3.651 ms  plan:
  Query Text: SELECT count(*)
              FROM pg_class, pg_index
              WHERE oid = indrelid AND indisunique;
  Aggregate  (cost=16.79..16.80 rows=1 width=0) (actual time=3.626..3.627 rows=1 loops=1)
    ->  Hash Join  (cost=4.17..16.55 rows=92 width=0) (actual time=3.349..3.594 rows=92 loops=1)
          Hash Cond: (pg_class.oid = pg_index.indrelid)
          ->  Seq Scan on pg_class  (cost=0.00..9.55 rows=255 width=4) (actual time=0.016..0.140 rows=255 loops=1)
          ->  Hash  (cost=3.02..3.02 rows=92 width=4) (actual time=3.238..3.238 rows=92 loops=1)
                Buckets: 1024  Batches: 1  Memory Usage: 4kB
                ->  Seq Scan on pg_index  (cost=0.00..3.02 rows=92 width=4) (actual time=0.008..3.187 rows=92 loops=1)
                      Filter: indisunique

F.3.3. 作者

Takahiro Itagaki