目录
文档用途
当我们想要跟踪大型应用中未优化的查询时,可使用auto_explain模块提供的一种自动的记录慢速语句执行计划的方法。这种方法可以让我们不必手动的运行EXPLAIN语句,所以使用这种方式是很有帮助的。
详细信息
1、使用方法
要想使用这个模块,只需要把它加载到服务器中(只有数据库超级用户可以运行这条指令):
highgo=# LOAD 'auto_explain'; LOAD |
然后无论何时发生了意料之外的慢查询,我们都可以进行追踪。
2、配置参数介绍及示例
配置参数控制着auto_explain的行为。需要注意的是,默认情况下的行为是什么也不做,所以如果想要得到相关结果,必须至少要设置auto_explain.log_min_duration这个参数。注意,只有数据库超级用户才能设置以下参数。
1)auto_explain.log_min_duration(integer)
这个参数指的是最小语句执行时间,单位是毫秒,设置之后语句计划就会被记录。例如,设置此参数的值为250毫秒,那么运行时间在250毫秒及以上的语句会被记录下来。默认值为-1,表示不记录任何计划。
highgo=# SELECT count(*) FROM pg_class, pg_index WHERE oid = indrelid AND indisunique; count ------- 111 (1 row) |
如果将此参数设置为0,表示记录所有的计划。
highgo=# SET auto_explain.log_min_duration = 0; SET highgo=# SET auto_explain.log_analyze = true; SET highgo=# SELECT count(*) highgo-# FROM pg_class, pg_index highgo-# WHERE oid = indrelid AND indisunique; 日志: 00000: duration: 0.935 ms plan: Query Text: SELECT count(*) FROM pg_class, pg_index WHERE oid = indrelid AND indisunique; Aggregate (cost=22.25..22.26 rows=1 width=0) (actual time=0.925..0.925 rows=1 loops=1) -> Hash Join (cost=5.75..21.98 rows=111 width=0) (actual time=0.816..0.907 rows=111 loops=1) Hash Cond: (pg_class.oid = pg_index.indrelid) -> Index Only Scan using pg_class_oid_index on pg_class (cost=0.15..12.89 rows=316 width=4) (actual time=0.731..0.782 rows=317 loops=1) Heap Fetches: 87 -> Hash (cost=4.22..4.22 rows=111 width=4) (actual time=0.046..0.046 rows=111 loops=1) Buckets: 1024 Batches: 1 Memory Usage: 12kB -> Seq Scan on pg_index (cost=0.00..4.22 rows=111 width=4) (actual time=0.006..0.023 rows=111 loops=1) Filter: indisunique Rows Removed by Filter: 11 count ------- 111 (1 row) |
2)auto_explain.log_analyze(boolean)
设置这个参数使得当一个执行计划被记录时,会让EXPLAIN ANALYZE的结果,而不仅仅是EXPLAIN 的结果被打印出来。默认值为off。
highgo=# SELECT count(*) FROM pg_class, pg_index WHERE oid = indrelid AND indisunique; 日志: 00000: duration: 0.131 ms plan: Query Text: SELECT count(*) FROM pg_class, pg_index WHERE oid = indrelid AND indisunique; Aggregate (cost=22.25..22.26 rows=1 width=0) -> Hash Join (cost=5.75..21.98 rows=111 width=0) Hash Cond: (pg_class.oid = pg_index.indrelid) -> Index Only Scan using pg_class_oid_index on pg_class (cost=0.15..12.89 rows=316 width=4) -> Hash (cost=4.22..4.22 rows=111 width=4) Buckets: 1024 Batches: 1 Memory Usage: 12kB -> Seq Scan on pg_index (cost=0.00..4.22 rows=111 width=4) Filter: indisunique count ------- 111 (1 row) |
将此参数设置为on之后,就能获得EXPLAIN ANALYZE的结果。
highgo=# SELECT count(*) highgo-# FROM pg_class, pg_index highgo-# WHERE oid = indrelid AND indisunique; 日志: 00000: duration: 0.935 ms plan: Query Text: SELECT count(*) FROM pg_class, pg_index WHERE oid = indrelid AND indisunique; Aggregate (cost=22.25..22.26 rows=1 width=0) (actual time=0.925..0.925 rows=1 loops=1) -> Hash Join (cost=5.75..21.98 rows=111 width=0) (actual time=0.816..0.907 rows=111 loops=1) Hash Cond: (pg_class.oid = pg_index.indrelid) -> Index Only Scan using pg_class_oid_index on pg_class (cost=0.15..12.89 rows=316 width=4) (actual time=0.731..0.782 rows=317 loops=1) Heap Fetches: 87 -> Hash (cost=4.22..4.22 rows=111 width=4) (actual time=0.046..0.046 rows=111 loops=1) Buckets: 1024 Batches: 1 Memory Usage: 12kB -> Seq Scan on pg_index (cost=0.00..4.22 rows=111 width=4) (actual time=0.006..0.023 rows=111 loops=1) Filter: indisunique Rows Removed by Filter: 11 count ------- 111 (1 row) |
注意,将这个参数设置为on可能会对性能造成极大的不良影响,所以为了优化性能成本可以将它设置为off,代价是获得的信息会少一些。
3)auto_explain.log_buffers(boolean)
此参数控制着当一个执行计划被记录时,缓冲区用量统计信息是否被打印出来。这个参数只有当开启auto_explain.log_analyze后才有作用,默认为off。
将这个参数设置为on:
highgo=# SET auto_explain.log_buffers = on; SET highgo=# SELECT count(*) FROM pg_class, pg_index WHERE oid = indrelid AND indisunique; 日志: 00000: duration: 0.203 ms plan: Query Text: SELECT count(*) FROM pg_class, pg_index WHERE oid = indrelid AND indisunique; Aggregate (cost=22.25..22.26 rows=1 width=0) (actual time=0.197..0.197 rows=1 loops=1) Buffers: shared hit=31 -> Hash Join (cost=5.75..21.98 rows=111 width=0) (actual time=0.059..0.188 rows=111 loops=1) Hash Cond: (pg_class.oid = pg_index.indrelid) Buffers: shared hit=31 -> Index Only Scan using pg_class_oid_index on pg_class (cost=0.15..12.89 rows=316 width=4) (actual time=0.013..0.060 rows=317 loops=1) Heap Fetches: 87 Buffers: shared hit=28 -> Hash (cost=4.22..4.22 rows=111 width=4) (actual time=0.039..0.039 rows=111 loops=1) Buckets: 1024 Batches: 1 Memory Usage: 12kB Buffers: shared hit=3 -> Seq Scan on pg_index (cost=0.00..4.22 rows=111 width=4) (actual time=0.003..0.028 rows=111 loops=1) Filter: indisunique Rows Removed by Filter: 11 Buffers: shared hit=3 count ------- 111 (1 row) |
从结果中看到,缓冲区信息被打印出来。
4)auto_explain.log_timing(boolean)
此参数控制着当一个执行计划被记录时,是否每个节点的时间信息都被打印出来。这个参数只有当开auto_explain.log_analyze后才有作用,默认值为on。
将这个参数设置为on之后,时间信息就不会被打印出来:
highgo=# SET auto_explain.log_timing = off; SET highgo=# SELECT count(*) FROM pg_class, pg_index WHERE oid = indrelid AND indisunique; 日志: 00000: duration: 0.198 ms plan: Query Text: SELECT count(*) FROM pg_class, pg_index WHERE oid = indrelid AND indisunique; Aggregate (cost=22.25..22.26 rows=1 width=0) (actual rows=1 loops=1) Buffers: shared hit=31 -> Hash Join (cost=5.75..21.98 rows=111 width=0) (actual rows=111 loops=1) Hash Cond: (pg_class.oid = pg_index.indrelid) Buffers: shared hit=31 -> Index Only Scan using pg_class_oid_index on pg_class (cost=0.15..12.89 rows=316 width=4) (actual rows=317 loops=1) Heap Fetches: 87 Buffers: shared hit=28 -> Hash (cost=4.22..4.22 rows=111 width=4) (actual rows=111 loops=1) Buckets: 1024 Batches: 1 Memory Usage: 12kB Buffers: shared hit=3 -> Seq Scan on pg_index (cost=0.00..4.22 rows=111 width=4) (actual rows=111 loops=1) Filter: indisunique Rows Removed by Filter: 11 Buffers: shared hit=3 count ------- 111 (1 row) |
需要注意的是,在有些系统中重复读取系统时钟的开销会显著地降低查询速率。所以如果我们只想得到实际的行数信息,而不是精确的时间信息的话,建议将此参数设置为off。
5)auto_explain.log_triggers(boolean)
此参数使得当一个执行计划被记录时,触发器的执行统计信息也会被包含进去。这个参数只有当开启auto_explain.log_analyze后才有作用,默认值为off。
6)auto_explain.log_verbose(boolean)
此参数控制着当执行计划被记录时,是否打印细节信息。默认值为off。
如果将此参数设置为on,就能打印出细节信息:
highgo=# SET auto_explain.log_verbose = on; SET highgo=# SELECT count(*) FROM pg_class, pg_index WHERE oid = indrelid AND indisunique; 日志: 00000: duration: 0.116 ms plan: Query Text: SELECT count(*) FROM pg_class, pg_index WHERE oid = indrelid AND indisunique; Aggregate (cost=22.25..22.26 rows=1 width=0) (actual rows=1 loops=1) Output: count(*) Buffers: shared hit=31 -> Hash Join (cost=5.75..21.98 rows=111 width=0) (actual rows=111 loops=1) Hash Cond: (pg_class.oid = pg_index.indrelid) Buffers: shared hit=31 -> Index Only Scan using pg_class_oid_index on pg_catalog.pg_class (cost=0.15..12.89 rows=316 width=4) (actual rows=317 loops=1) Output: pg_class.oid Heap Fetches: 87 Buffers: shared hit=28 -> Hash (cost=4.22..4.22 rows=111 width=4) (actual rows=111 loops=1) Output: pg_index.indrelid Buckets: 1024 Batches: 1 Memory Usage: 12kB Buffers: shared hit=3 -> Seq Scan on pg_catalog.pg_index (cost=0.00..4.22 rows=111 width=4) (actual rows=111 loops=1) Output: pg_index.indrelid Filter: pg_index.indisunique Rows Removed by Filter: 11 Buffers: shared hit=3 count ------- 111 (1 row) |
更加详细的参数设置请登录【瀚高技术支持平台】查看
https://support.highgo.com/#/index/docContent/a540bd27037b31e6