PostgreSQL跟蹤函式內部執行計畫方法

2021-10-06 06:27:27 字數 4810 閱讀 5405

很多人可能在使用pg時會碰到這樣的問題:乙個sql單獨拿出來執行很快,但是放到函式裡面執行就很慢,想要知道函式裡面究竟慢在**,但是卻無從下手。因為我們沒辦法像對單個sql一樣直接explain來獲取執行計畫。

例如在oracle中我們可以通過例如10046trace這種方式來看看函式內部慢在**,那麼在pg中該如何去檢視內部的執行計畫呢?

auto_explain是pg自帶的乙個模組,為我們提供了一種方式來自動記錄慢速語句的執行計畫,而不需要手工執行explain。這在大型應用中追蹤未被優化的查詢時有用。

auto_explain的輸出更詳細的解釋可以參考expolain的解釋,或者man explain。

開啟auto_explain有兩種方式:

1、 通過配置檔案postgresql.conf

需要重啟資料庫。

2、通過load 『auto_explain』;

這個只在當前session生效,不需要重啟資料庫, 需要超級使用者許可權。

其實還可以設定local_preload_libraries,session_preload_libraries引數來啟用。

例子:

1. 修改postgresql.conf配置檔案:

shared_preload_libraries =

'auto_explain'

新增如下配置:

auto_explain.log_min_duration = 0  # 為了方便檢視,這裡把時間設定為0,所有sql都會被auto_explain捕獲輸出.實際使用的時候適當調大。如 100ms  

auto_explain.log_analyze =

true

# 以下可選

auto_explain.log_verbose =

true

auto_explain.log_buffers =

true

auto_explain.log_nested_statements =

true

2、重啟資料庫

預設情況下日誌記錄在日誌檔案中。

查詢:

bill=

# select count(*) from tb1;

count

---------

1000000(1

row)

檢視log日誌:

bill@test180

-> tail -f postgresql-

2020-05

-18_110158.csv

2020-05

-1811:28:52.056 cst,

"bill"

,"bill"

,2160

,"[local]"

,5ec1fd1a.

870,3,

"select"

,2020-05

-1811:12:26 cst,3/

60,0,log,

00000

,"duration: 70.772 ms plan:

query text: select count(*) from tb1;

finalize aggregate (cost=14542.55..14542.56 rows=1 width=8) (actual time=68.293..68.293 rows=1 loops=1)

output: count(*)

buffers: shared hit=8334

-> gather (cost=14542.33..14542.54 rows=2 width=8) (actual time=68.169..70.752 rows=3 loops=1)

output: (partial count(*))

workers planned: 2

workers launched: 2

buffers: shared hit=8334

-> partial aggregate (cost=13542.33..13542.34 rows=1 width=8) (actual time=65.305..65.305 rows=1 loops=3)

output: partial count(*)

buffers: shared hit=8334

worker 0: actual time=64.003..64.003 rows=1 loops=1

buffers: shared hit=2590

worker 1: actual time=63.998..63.998 rows=1 loops=1

buffers: shared hit=2654

-> parallel seq scan on public.tb1 (cost=0.00..12500.67 rows=416667 width=0) (actual time=0.016..41.887 rows=333333 loops=3)

output: id, info

buffers: shared hit=8334

worker 0: actual time=0.018..42.208 rows=310800 loops=1

buffers: shared hit=2590

worker 1: actual time=0.018..42.225 rows=318400 loops=1

buffers: shared hit=2654",,

,,,,

,,"explain_executorend, auto_explain.c:415"

,"psql"

3、如果你不想看日誌這麼麻煩,想在client直接顯示,也很方便,設定client_min_messages='log』就可以看到auto explain的輸出了。

set client_min_messages=

'log'

;set auto_explain.log_min_duration = 0;

set auto_explain.log_analyze =

true

;set auto_explain.log_verbose =

true

;set auto_explain.log_buffers =

true

;set auto_explain.log_nested_statements =

true

;

我們來看乙個輸出函式執行計畫的例子。

先建立乙個簡單的函式:

bill=

# create function f1(c1 int) returns int as $$

bill$# declare

bill$# rec int;

bill$# begin

bill$# select count(*) from tb1 where id < c1 into rec;

bill$# return rec;

bill$# end;

bill$# $$ language plpgsql strict;

呼叫函式:

可以看到執行計畫直接輸出出來了,即使函式十分複雜,內部sql的執行計畫也可以依次輸出,這樣我們就知道函式慢在**了。

bill=

# select f1(100);

psql: log: duration: 0.055 ms plan:

query text: select

count(*

)from tb1 where id < c1

aggregate (cost=

5.03..5

.04rows

=1 width=8)

(actual time

=0.053..0

.053

rows

=1 loops=1)

output: count(*

) buffers: shared hit=4-

>

index only scan using idx_tb1 on

public

.tb1 (cost=

0.42..4

.78rows

=100 width=0)

(actual time

=0.019..0

.040

rows

=99 loops=1)

output: id

index cond: (tb1.id <

100)

heap fetches: 99

buffers: shared hit=

4psql: log: duration: 0.677 ms plan:

query text: select f1(

100)

;result (cost=

0.00..0

.26rows

=1 width=4)

(actual time

=0.672..0

.672

rows

=1 loops=1)

output: f1(

100)

buffers: shared hit=

39read=1

f1 ----99(

1row

)

PostgreSQL 慢查詢SQL語句跟蹤

示例 啟用 sql 跟蹤 postgresql 日誌支援的輸出格式有 stderr 預設 csvlog syslog 一般的錯誤跟蹤,只需在配置檔案 postgresql.conf 簡單設定幾個引數,當然還有錯誤級別等要設定。logging collector on log destination ...

PostgreSQL 慢查詢SQL跟蹤操作

postgresql 開啟慢sql捕獲在排查問題時是個很有效的手段。根據慢sql讓我在工作中真正解決了實際問題,很有幫助。postgresql 日誌支援的輸出格式有 stderr 預設 csvlog syslog 一般的錯誤跟蹤,只需在配置檔案 postgresql.conf 簡單設定幾個引數,當然...

postgreSQL常用函式

select coalesce sum duration 0 若sum duration 返回值為空,則為其賦值0 select to date 2013 12 20 yyyy mm dd 字串轉化為date型別 select date 2013 10 28 01 00 interval 50 mi...