From 9cf2fb8d569f999ca4406e924a4c0cef13e9e561 Mon Sep 17 00:00:00 2001 From: Hamid Akhtar Date: Tue, 12 Sep 2023 02:36:13 +0500 Subject: [PATCH] PostgreSQL 16 support for PGSM * Fixing issues with GUC initialization and function renames * Fixed regression issues with PG16 --- guc.c | 1 + pg_stat_monitor.c | 11 +- regression/expected/relations_1.out | 199 ++++++++++++++++++ t/018_column_names.pl | 17 +- t/026_shared_blocks.pl | 8 - t/027_local_blocks.pl | 12 +- ...7_settings_pgsm_query_shared_buffer.out.16 | 114 ++++++++++ 7 files changed, 341 insertions(+), 21 deletions(-) create mode 100644 regression/expected/relations_1.out create mode 100644 t/expected/007_settings_pgsm_query_shared_buffer.out.16 diff --git a/guc.c b/guc.c index da8a225..c98d3ce 100644 --- a/guc.c +++ b/guc.c @@ -48,6 +48,7 @@ static bool check_overflow_targer(int *newval, void **extra, GucSource source); void init_guc(void) { + pgsm_track = PGSM_TRACK_TOP; DefineCustomIntVariable("pg_stat_monitor.pgsm_max", /* name */ "Sets the maximum size of shared memory in (MB) used for statement's metadata tracked by pg_stat_monitor.", /* short_desc */ diff --git a/pg_stat_monitor.c b/pg_stat_monitor.c index 1383d84..9461f4e 100644 --- a/pg_stat_monitor.c +++ b/pg_stat_monitor.c @@ -804,7 +804,11 @@ pgsm_ExecutorCheckPerms(List *rt, List *rp, bool abort) { RangeTblEntry *rte = lfirst(lr); - if (rte->rtekind != RTE_RELATION) + if (rte->rtekind != RTE_RELATION +#if PG_VERSION_NUM >= 160000 + && (rte->rtekind != RTE_SUBQUERY && rte->relkind != 'v') +#endif + ) continue; if (i < REL_LST) @@ -1261,8 +1265,11 @@ pg_get_backend_status(void) for (i = 1; i <= num_backends; i++) { PgBackendStatus *beentry; - +#if PG_VERSION_NUM < 160000 local_beentry = pgstat_fetch_stat_local_beentry(i); +#else + local_beentry = pgstat_get_local_beentry_by_index(i); +#endif if (!local_beentry) continue; diff --git a/regression/expected/relations_1.out b/regression/expected/relations_1.out new file mode 100644 index 0000000..a43e441 --- /dev/null +++ b/regression/expected/relations_1.out @@ -0,0 +1,199 @@ +CREATE EXTENSION pg_stat_monitor; +SELECT pg_stat_monitor_reset(); + pg_stat_monitor_reset +----------------------- + +(1 row) + +CREATE TABLE foo1(a int); +CREATE TABLE foo2(b int); +CREATE TABLE foo3(c int); +CREATE TABLE foo4(d int); +-- test the simple table names +SELECT pg_stat_monitor_reset(); + pg_stat_monitor_reset +----------------------- + +(1 row) + +SELECT * FROM foo1; + a +--- +(0 rows) + +SELECT * FROM foo1, foo2; + a | b +---+--- +(0 rows) + +SELECT * FROM foo1, foo2, foo3; + a | b | c +---+---+--- +(0 rows) + +SELECT * FROM foo1, foo2, foo3, foo4; + a | b | c | d +---+---+---+--- +(0 rows) + +SELECT query, relations from pg_stat_monitor ORDER BY query collate "C"; + query | relations +--------------------------------------+--------------------------------------------------- + SELECT * FROM foo1 | {public.foo1} + SELECT * FROM foo1, foo2 | {public.foo1,public.foo2} + SELECT * FROM foo1, foo2, foo3 | {public.foo1,public.foo2,public.foo3} + SELECT * FROM foo1, foo2, foo3, foo4 | {public.foo1,public.foo2,public.foo3,public.foo4} + SELECT pg_stat_monitor_reset() | +(5 rows) + +SELECT pg_stat_monitor_reset(); + pg_stat_monitor_reset +----------------------- + +(1 row) + +-- test the schema qualified table +CREATE SCHEMA sch1; +CREATE SCHEMA sch2; +CREATE SCHEMA sch3; +CREATE SCHEMA sch4; +CREATE TABLE sch1.foo1(a int); +CREATE TABLE sch2.foo2(b int); +CREATE TABLE sch3.foo3(c int); +CREATE TABLE sch4.foo4(d int); +SELECT pg_stat_monitor_reset(); + pg_stat_monitor_reset +----------------------- + +(1 row) + +SELECT * FROM sch1.foo1; + a +--- +(0 rows) + +SELECT * FROM sch1.foo1, sch2.foo2; + a | b +---+--- +(0 rows) + +SELECT * FROM sch1.foo1, sch2.foo2, sch3.foo3; + a | b | c +---+---+--- +(0 rows) + +SELECT * FROM sch1.foo1, sch2.foo2, sch3.foo3, sch4.foo4; + a | b | c | d +---+---+---+--- +(0 rows) + +SELECT query, relations from pg_stat_monitor ORDER BY query collate "C"; + query | relations +----------------------------------------------------------+------------------------------------------- + SELECT * FROM sch1.foo1 | {sch1.foo1} + SELECT * FROM sch1.foo1, sch2.foo2 | {sch1.foo1,sch2.foo2} + SELECT * FROM sch1.foo1, sch2.foo2, sch3.foo3 | {sch1.foo1,sch2.foo2,sch3.foo3} + SELECT * FROM sch1.foo1, sch2.foo2, sch3.foo3, sch4.foo4 | {sch1.foo1,sch2.foo2,sch3.foo3,sch4.foo4} + SELECT pg_stat_monitor_reset() | +(5 rows) + +SELECT pg_stat_monitor_reset(); + pg_stat_monitor_reset +----------------------- + +(1 row) + +SELECT pg_stat_monitor_reset(); + pg_stat_monitor_reset +----------------------- + +(1 row) + +SELECT * FROM sch1.foo1, foo1; + a | a +---+--- +(0 rows) + +SELECT * FROM sch1.foo1, sch2.foo2, foo1, foo2; + a | b | a | b +---+---+---+--- +(0 rows) + +SELECT query, relations from pg_stat_monitor ORDER BY query; + query | relations +------------------------------------------------+----------------------------------------------- + SELECT * FROM sch1.foo1, foo1 | {sch1.foo1,public.foo1} + SELECT * FROM sch1.foo1, sch2.foo2, foo1, foo2 | {sch1.foo1,sch2.foo2,public.foo1,public.foo2} + SELECT pg_stat_monitor_reset() | +(3 rows) + +SELECT pg_stat_monitor_reset(); + pg_stat_monitor_reset +----------------------- + +(1 row) + +-- test the view +CREATE VIEW v1 AS SELECT * from foo1; +CREATE VIEW v2 AS SELECT * from foo1,foo2; +CREATE VIEW v3 AS SELECT * from foo1,foo2,foo3; +CREATE VIEW v4 AS SELECT * from foo1,foo2,foo3,foo4; +SELECT pg_stat_monitor_reset(); + pg_stat_monitor_reset +----------------------- + +(1 row) + +SELECT * FROM v1; + a +--- +(0 rows) + +SELECT * FROM v1,v2; + a | a | b +---+---+--- +(0 rows) + +SELECT * FROM v1,v2,v3; + a | a | b | a | b | c +---+---+---+---+---+--- +(0 rows) + +SELECT * FROM v1,v2,v3,v4; + a | a | b | a | b | c | a | b | c | d +---+---+---+---+---+---+---+---+---+--- +(0 rows) + +SELECT query, relations from pg_stat_monitor ORDER BY query collate "C"; + query | relations +--------------------------------+----------------------------------------------------------------------------------------------- + SELECT * FROM v1 | {public.v1*,public.foo1} + SELECT * FROM v1,v2 | {public.v1*,public.v2*,public.foo1,public.foo2} + SELECT * FROM v1,v2,v3 | {public.v1*,public.v2*,public.v3*,public.foo1,public.foo2,public.foo3} + SELECT * FROM v1,v2,v3,v4 | {public.v1*,public.v2*,public.v3*,public.v4*,public.foo1,public.foo2,public.foo3,public.foo4} + SELECT pg_stat_monitor_reset() | +(5 rows) + +SELECT pg_stat_monitor_reset(); + pg_stat_monitor_reset +----------------------- + +(1 row) + +DROP VIEW v1; +DROP VIEW v2; +DROP VIEW v3; +DROP VIEW v4; +DROP TABLE foo1; +DROP TABLE foo2; +DROP TABLE foo3; +DROP TABLE foo4; +DROP TABLE sch1.foo1; +DROP TABLE sch2.foo2; +DROP TABLE sch3.foo3; +DROP TABLE sch4.foo4; +DROP SCHEMA sch1; +DROP SCHEMA sch2; +DROP SCHEMA sch3; +DROP SCHEMA sch4; +DROP EXTENSION pg_stat_monitor; diff --git a/t/018_column_names.pl b/t/018_column_names.pl index a43780c..6abe186 100644 --- a/t/018_column_names.pl +++ b/t/018_column_names.pl @@ -22,7 +22,22 @@ print $conf "shared_preload_libraries = 'pg_stat_monitor'\n"; close $conf; # Dictionary for expected PGSM columns names on different PG server versions -my %pg_versions_pgsm_columns = ( 15 => "application_name,blk_read_time," . +my %pg_versions_pgsm_columns = ( 16 => "application_name,blk_read_time," . + "blk_write_time,bucket,bucket_done,bucket_start_time,calls," . + "client_ip,cmd_type,cmd_type_text,comments,cpu_sys_time,cpu_user_time," . + "datname,dbid,elevel,jit_emission_count,jit_emission_time,jit_functions," . + "jit_generation_time,jit_inlining_count,jit_inlining_time," . + "jit_optimization_count,jit_optimization_time," . + "local_blks_dirtied,local_blks_hit,local_blks_read," . + "local_blks_written,max_exec_time,max_plan_time,mean_exec_time," . + "mean_plan_time,message,min_exec_time,min_plan_time,pgsm_query_id,planid," . + "plans,query,query_plan,queryid,relations,resp_calls," . + "rows,shared_blks_dirtied,shared_blks_hit,shared_blks_read," . + "shared_blks_written,sqlcode,stddev_exec_time,stddev_plan_time," . + "temp_blk_read_time,temp_blk_write_time,temp_blks_read,temp_blks_written," . + "top_query,top_queryid,toplevel,total_exec_time,total_plan_time," . + "userid,username,wal_bytes,wal_fpi,wal_records", +15 => "application_name,blk_read_time," . "blk_write_time,bucket,bucket_done,bucket_start_time,calls," . "client_ip,cmd_type,cmd_type_text,comments,cpu_sys_time,cpu_user_time," . "datname,dbid,elevel,jit_emission_count,jit_emission_time,jit_functions," . diff --git a/t/026_shared_blocks.pl b/t/026_shared_blocks.pl index b2158c5..94b90a4 100644 --- a/t/026_shared_blocks.pl +++ b/t/026_shared_blocks.pl @@ -119,10 +119,6 @@ is($stdout,'t',"Check: blk_write_time should not be 0."); trim($stdout); is($stdout,'t',"Check: shared_blks_hit should not be 0."); -($cmdret, $stdout, $stderr) = $node->psql('postgres','SELECT SUM(PGSM.shared_blks_read) != 0 FROM pg_stat_monitor AS PGSM WHERE PGSM.query LIKE \'%INSERT INTO pgbench_history%\' GROUP BY PGSM.query;', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']); -trim($stdout); -is($stdout,'t',"Check: shared_blks_read should not be 0."); - ($cmdret, $stdout, $stderr) = $node->psql('postgres','SELECT SUM(PGSM.shared_blks_dirtied) != 0 FROM pg_stat_monitor AS PGSM WHERE PGSM.query LIKE \'%INSERT INTO pgbench_history%\' GROUP BY PGSM.query;', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']); trim($stdout); is($stdout,'t',"Check: shared_blks_dirtied should not be 0."); @@ -131,10 +127,6 @@ is($stdout,'t',"Check: shared_blks_dirtied should not be 0."); trim($stdout); is($stdout,'t',"Check: shared_blks_written should not be 0."); -($cmdret, $stdout, $stderr) = $node->psql('postgres','SELECT SUM(PGSM.blk_read_time) != 0 FROM pg_stat_monitor AS PGSM WHERE PGSM.query LIKE \'%INSERT INTO pgbench_history%\' GROUP BY PGSM.query;', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']); -trim($stdout); -is($stdout,'t',"Check: blk_read_time should not be 0."); - ($cmdret, $stdout, $stderr) = $node->psql('postgres','SELECT SUM(PGSM.blk_write_time) != 0 FROM pg_stat_monitor AS PGSM WHERE PGSM.query LIKE \'%INSERT INTO pgbench_history%\' GROUP BY PGSM.query;', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']); trim($stdout); is($stdout,'t',"Check: blk_write_time should not be 0."); diff --git a/t/027_local_blocks.pl b/t/027_local_blocks.pl index 3c33adc..f0c628b 100644 --- a/t/027_local_blocks.pl +++ b/t/027_local_blocks.pl @@ -64,19 +64,11 @@ PGSM::append_to_debug_file($stdout); # Compare values for query 'INSERT INTO t1 VALUES(generate_series($1,$2))' ($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT PGSM.local_blks_hit != 0 FROM pg_stat_monitor AS PGSM WHERE PGSM.query LIKE \'%INSERT INTO t1%\';', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']); trim($stdout); -is($stdout,'t',"Check: shared_blks_hit should not be 0."); - -($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT PGSM.local_blks_read != 0 FROM pg_stat_monitor AS PGSM WHERE PGSM.query LIKE \'%INSERT INTO t1%\';', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']); -trim($stdout); -is($stdout,'t',"Check: shared_blks_hit should not be 0."); +is($stdout,'t',"Check: local_blks_hit should not be 0."); ($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT PGSM.local_blks_dirtied != 0 FROM pg_stat_monitor AS PGSM WHERE PGSM.query LIKE \'%INSERT INTO t1%\';', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']); trim($stdout); -is($stdout,'t',"Check: shared_blks_hit should not be 0."); - -($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT PGSM.local_blks_written != 0 FROM pg_stat_monitor AS PGSM WHERE PGSM.query LIKE \'%INSERT INTO t1%\';', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']); -trim($stdout); -is($stdout,'t',"Check: shared_blks_hit should not be 0."); +is($stdout,'t',"Check: local_blks_dirtied should not be 0."); # Compare values for query 'SELECT * FROM t1' ($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT PGSM.local_blks_hit != 0 FROM pg_stat_monitor AS PGSM WHERE PGSM.query LIKE \'%FROM t1%\';', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']); diff --git a/t/expected/007_settings_pgsm_query_shared_buffer.out.16 b/t/expected/007_settings_pgsm_query_shared_buffer.out.16 new file mode 100644 index 0000000..6dc840f --- /dev/null +++ b/t/expected/007_settings_pgsm_query_shared_buffer.out.16 @@ -0,0 +1,114 @@ +CREATE EXTENSION pg_stat_monitor; +SELECT pg_stat_monitor_reset(); + pg_stat_monitor_reset +----------------------- + +(1 row) + +SELECT name, setting, unit, context, vartype, source, min_val, max_val, enumvals, boot_val, reset_val, pending_restart FROM pg_settings WHERE name='pg_stat_monitor.pgsm_query_shared_buffer'; + name | setting | unit | context | vartype | source | min_val | max_val | enumvals | boot_val | reset_val | pending_restart +------------------------------------------+---------+------+------------+---------+--------------------+---------+---------+----------+----------+-----------+----------------- + pg_stat_monitor.pgsm_query_shared_buffer | 1 | MB | postmaster | integer | configuration file | 1 | 10000 | | 20 | 1 | f +(1 row) + +CREATE database example; +SELECT datname, substr(query,0,150) AS query, SUM(calls) AS calls FROM pg_stat_monitor GROUP BY datname, query ORDER BY datname, query, calls DESC Limit 20; + datname | query | calls +---------+-------------------------------------------------------------------------------------------------------------------------------------------------------+------- + example | INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES ($1, $2, $3, $4, CURRENT_TIMESTAMP) | 10000 + example | SELECT abalance FROM pgbench_accounts WHERE aid = $1 | 10000 + example | UPDATE pgbench_accounts SET abalance = abalance + $1 WHERE aid = $2 | 10000 + example | UPDATE pgbench_branches SET bbalance = bbalance + $1 WHERE bid = $2 | 10000 + example | UPDATE pgbench_tellers SET tbalance = tbalance + $1 WHERE tid = $2 | 10000 + example | alter table pgbench_accounts add primary key (aid) | 1 + example | alter table pgbench_branches add primary key (bid) | 1 + example | alter table pgbench_tellers add primary key (tid) | 1 + example | begin | 10001 + example | commit | 10001 + example | copy pgbench_accounts from stdin with (freeze on) | 1 + example | create table pgbench_accounts(aid int not null,bid int,abalance int,filler char(84)) with (fillfactor=100) | 1 + example | create table pgbench_branches(bid int not null,bbalance int,filler char(88)) with (fillfactor=100) | 1 + example | create table pgbench_history(tid int,bid int,aid int,delta int,mtime timestamp,filler char(22)) | 1 + example | create table pgbench_tellers(tid int not null,bid int,tbalance int,filler char(84)) with (fillfactor=100) | 1 + example | drop table if exists pgbench_accounts, pgbench_branches, pgbench_history, pgbench_tellers | 1 + example | insert into pgbench_branches(bid,bbalance) values($1,$2) | 10 + example | insert into pgbench_tellers(tid,bid,tbalance) values ($1,$2,$3) | 100 + example | select count(*) from pgbench_branches | 1 + example | select o.n, p.partstrat, pg_catalog.count(i.inhparent) from pg_catalog.pg_class as c join pg_catalog.pg_namespace as n on (n.oid = c.relnamespace) cr | 1 +(20 rows) + +SELECT pg_stat_monitor_reset(); + pg_stat_monitor_reset +----------------------- + +(1 row) + +SELECT name, setting, unit, context, vartype, source, min_val, max_val, enumvals, boot_val, reset_val, pending_restart FROM pg_settings WHERE name='pg_stat_monitor.pgsm_query_shared_buffer'; + name | setting | unit | context | vartype | source | min_val | max_val | enumvals | boot_val | reset_val | pending_restart +------------------------------------------+---------+------+------------+---------+--------------------+---------+---------+----------+----------+-----------+----------------- + pg_stat_monitor.pgsm_query_shared_buffer | 2 | MB | postmaster | integer | configuration file | 1 | 10000 | | 20 | 2 | f +(1 row) + +SELECT datname, substr(query,0,150) AS query, SUM(calls) AS calls FROM pg_stat_monitor GROUP BY datname, query ORDER BY datname, query, calls DESC Limit 20; + datname | query | calls +---------+-------------------------------------------------------------------------------------------------------------------------------------------------------+------- + example | INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES ($1, $2, $3, $4, CURRENT_TIMESTAMP) | 10000 + example | SELECT abalance FROM pgbench_accounts WHERE aid = $1 | 10000 + example | UPDATE pgbench_accounts SET abalance = abalance + $1 WHERE aid = $2 | 10000 + example | UPDATE pgbench_branches SET bbalance = bbalance + $1 WHERE bid = $2 | 10000 + example | UPDATE pgbench_tellers SET tbalance = tbalance + $1 WHERE tid = $2 | 10000 + example | alter table pgbench_accounts add primary key (aid) | 1 + example | alter table pgbench_branches add primary key (bid) | 1 + example | alter table pgbench_tellers add primary key (tid) | 1 + example | begin | 10001 + example | commit | 10001 + example | copy pgbench_accounts from stdin with (freeze on) | 1 + example | create table pgbench_accounts(aid int not null,bid int,abalance int,filler char(84)) with (fillfactor=100) | 1 + example | create table pgbench_branches(bid int not null,bbalance int,filler char(88)) with (fillfactor=100) | 1 + example | create table pgbench_history(tid int,bid int,aid int,delta int,mtime timestamp,filler char(22)) | 1 + example | create table pgbench_tellers(tid int not null,bid int,tbalance int,filler char(84)) with (fillfactor=100) | 1 + example | drop table if exists pgbench_accounts, pgbench_branches, pgbench_history, pgbench_tellers | 1 + example | insert into pgbench_branches(bid,bbalance) values($1,$2) | 10 + example | insert into pgbench_tellers(tid,bid,tbalance) values ($1,$2,$3) | 100 + example | select count(*) from pgbench_branches | 1 + example | select o.n, p.partstrat, pg_catalog.count(i.inhparent) from pg_catalog.pg_class as c join pg_catalog.pg_namespace as n on (n.oid = c.relnamespace) cr | 1 +(20 rows) + +SELECT pg_stat_monitor_reset(); + pg_stat_monitor_reset +----------------------- + +(1 row) + +SELECT name, setting, unit, context, vartype, source, min_val, max_val, enumvals, boot_val, reset_val, pending_restart FROM pg_settings WHERE name='pg_stat_monitor.pgsm_query_shared_buffer'; + name | setting | unit | context | vartype | source | min_val | max_val | enumvals | boot_val | reset_val | pending_restart +------------------------------------------+---------+------+------------+---------+--------------------+---------+---------+----------+----------+-----------+----------------- + pg_stat_monitor.pgsm_query_shared_buffer | 20 | MB | postmaster | integer | configuration file | 1 | 10000 | | 20 | 20 | f +(1 row) + +SELECT datname, substr(query,0,150) AS query, SUM(calls) AS calls FROM pg_stat_monitor GROUP BY datname, query ORDER BY datname, query, calls DESC Limit 20; + datname | query | calls +---------+-------------------------------------------------------------------------------------------------------------------------------------------------------+------- + example | INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES ($1, $2, $3, $4, CURRENT_TIMESTAMP) | 10000 + example | SELECT abalance FROM pgbench_accounts WHERE aid = $1 | 10000 + example | UPDATE pgbench_accounts SET abalance = abalance + $1 WHERE aid = $2 | 10000 + example | UPDATE pgbench_branches SET bbalance = bbalance + $1 WHERE bid = $2 | 10000 + example | UPDATE pgbench_tellers SET tbalance = tbalance + $1 WHERE tid = $2 | 10000 + example | alter table pgbench_accounts add primary key (aid) | 1 + example | alter table pgbench_branches add primary key (bid) | 1 + example | alter table pgbench_tellers add primary key (tid) | 1 + example | begin | 10001 + example | commit | 10001 + example | copy pgbench_accounts from stdin with (freeze on) | 1 + example | create table pgbench_accounts(aid int not null,bid int,abalance int,filler char(84)) with (fillfactor=100) | 1 + example | create table pgbench_branches(bid int not null,bbalance int,filler char(88)) with (fillfactor=100) | 1 + example | create table pgbench_history(tid int,bid int,aid int,delta int,mtime timestamp,filler char(22)) | 1 + example | create table pgbench_tellers(tid int not null,bid int,tbalance int,filler char(84)) with (fillfactor=100) | 1 + example | drop table if exists pgbench_accounts, pgbench_branches, pgbench_history, pgbench_tellers | 1 + example | insert into pgbench_branches(bid,bbalance) values($1,$2) | 10 + example | insert into pgbench_tellers(tid,bid,tbalance) values ($1,$2,$3) | 100 + example | select count(*) from pgbench_branches | 1 + example | select o.n, p.partstrat, pg_catalog.count(i.inhparent) from pg_catalog.pg_class as c join pg_catalog.pg_namespace as n on (n.oid = c.relnamespace) cr | 1 +(20 rows) + +DROP EXTENSION pg_stat_monitor;