with recursive t (inhrelid, inhparent, depth) 
as (
        select  inhrelid, inhparent, 1 
        from    pg_inherits pi
        union all
        select  pi.inhrelid, pi.inhparent, depth + 1
        from    t, pg_inherits pi
        where   pi.inhparent = t.inhrelid
)
select pa.rolname,
       (select relname from pg_class where oid = pi.inhparent) as table_name,
       pcs.relname as partition_name,
       pt.spcname as tablespace_name,
       case ppt.partstrat when 'l' then 'list' when 'r' then 'range' else 'not partition' end as partition_type,
       dr.DEGREE,
       pc.reltuples::int as row_nums,
       pg_size_pretty(pg_table_size(pc.oid)) as size,
       pg_get_expr(pc.relpartbound, pc.oid) as partition_value
from    pg_class pcs
join    pg_inherits pi 
        on pc.oid = pi.inhrelid
join    pg_partitioned_table ppt 
        on ppt.partrelid = pi.inhparent
join    pg_authid pa 
        on pc.relowner = pa.oid
join    pg_tablespace pt 
        on pt.oid = case 
                        when pc.reltablespace = 0 
                            then (
                                    select  dattablespace 
                                    from    pg_database 
                                    where   datname=current_database()
                                 )
                        else pc.reltablespace 
                    end
join (
        select inhrelid, inhparent, max(depth) as degree
        from t
        group by inhrelid, inhparent
     ) dr 
     on dr.inhrelid = pc.oid
WHERE   DEGREE='1'
order by degree, table_name, partition_name;
블로그 이미지

운명을바꾸는자

IT와 함께 살아가는 삶

,

PostgreSQL Top SQL 추출 스크립트


do $$
declare
   has_pg_stat_statements boolean;
begin
   select count(*)>0 from pg_extension where extname = 'pg_stat_statements' into has_pg_stat_statements;
   if has_pg_stat_statements = false then
        create extension pg_stat_statements;
        raise notice 'create extension pg_stat_statements';
   end if;
end
$$;

select
        queryid,
        sum( calls ) as calls,
        round(( sum( total_time )/ 1000 )::numeric, 2 ) as total_time,
        round(( min( min_time )/ 1000 )::numeric, 2 ) as min_time,
        round(( max( max_time )/ 1000 )::numeric, 2 ) as max_time,
        round((( sum( mean_time )/ 1000 )/ count(*))::numeric, 2 ) as mean_time,
        (
                sum( rows )/ count(*)
        )::int as rows,
        (
                sum( shared_blks_hit )/ count(*)
        )::int as shared_blks_hit,
        max( query ) as query
from
        pg_stat_statements ptt
where
        dbid in(
                select
                        oid
                from
                        pg_database
                where
                        datname = current_database()
        )
        and strpos(
                query,
                'create'
        )= 0
        and strpos(
                query,
                'drop'
        )= 0
        and strpos(
                query,
                'copy'
        )= 0
        and strpos(
                query,
                'pg_stat_user'
        )= 0
        and strpos(
                query,
                'vacuum'
        )= 0
group by
        queryid
order by
        total_time desc,
        mean_time desc limit 50;
블로그 이미지

운명을바꾸는자

IT와 함께 살아가는 삶

,

PostgreSQL Vacuum 수행 필요 대상 추출 스크립트



- Vacuum threshold(autovacuum 임계값) = vacuum base threshold + vacuum scale factor * number of tuples


WITH avt AS (

    SELECT 

            setting AS autovacuum_vacuum_threshold 

    FROM    pg_settings 

    WHERE   name = 'autovacuum_vacuum_threshold'

)

, vsf AS (

    SELECT  setting AS autovacuum_vacuum_scale_factor 

    FROM    pg_settings 

    WHERE   name = 'autovacuum_vacuum_scale_factor'

)

, fma AS (

    SELECT  setting AS autovacuum_freeze_max_age 

    FROM    pg_settings 

    WHERE   name = 'autovacuum_freeze_max_age'

)

, sto AS (

    select  opt_oid

          , split_part(setting, '=', 1) as param

          , split_part(setting, '=', 2) as value 

    from    (

                select 

                        oid opt_oid

                      , unnest(reloptions) setting 

                from    pg_class

            ) opt

)

SELECT  '"'||ns.nspname||'"."'||c.relname||'"' as relation

      , pg_size_pretty(pg_table_size(c.oid)) as table_size

      , age(relfrozenxid) as xid_age

      , coalesce(cfma.value::float, autovacuum_freeze_max_age::float) as autovacuum_freeze_max_age

      , (coalesce(cavt.value::float, autovacuum_vacuum_threshold::float) + coalesce(cvsf.value::float,autovacuum_vacuum_scale_factor::float) * c.reltuples) as autovacuum_vacuum_tuples

      , n_dead_tup as dead_tuples

FROM    pg_class c 

        join pg_namespace ns 

        on  ns.oid = c.relnamespace

        join pg_stat_all_tables stat 

        on  stat.relid = c.oid

        join avt 

        on (1=1) join vsf 

        on (1=1) join fma 

        on (1=1)

        left join sto cavt 

        on cavt.param = 'autovacuum_vacuum_threshold' 

        and c.oid = cavt.opt_oid

        left join sto cvsf 

        on cvsf.param = 'autovacuum_vacuum_scale_factor' 

        and c.oid = cvsf.opt_oid

        left join sto cfma 

        on cfma.param = 'autovacuum_freeze_max_age' 

        and c.oid = cfma.opt_oid

WHERE   c.relkind = 'r' and nspname <> 'pg_catalog'

and     (

            age(relfrozenxid) >= coalesce(cfma.value::float, autovacuum_freeze_max_age::float)

            or

            coalesce(cavt.value::float, autovacuum_vacuum_threshold::float) + coalesce(cvsf.value::float,autovacuum_vacuum_scale_factor::float) * c.reltuples <= n_dead_tup

        )

ORDER BY age(relfrozenxid) DESC;


블로그 이미지

운명을바꾸는자

IT와 함께 살아가는 삶

,

PostgreSQL LOCK TREE 조회 스크립트



WITH RECURSIVE lt AS (

    SELECT   p.datname

           , p.usename

           , p.pid

           , pg_blocking_pids(p.pid) AS blocking_by

           , p.application_name

           , p.wait_event_type

           , p.state

           , p.query_start

           , p.query

           , ( 

SELECT array_agg(( SELECT relname 

                                    FROM pg_class pc 

                                   WHERE pc.oid = pl.relation ))

                 FROM pg_locks pl

                 WHERE pl.pid = p.pid

                      AND locktype = 'relation'

             ) AS relation

           , 0 AS level

           , row_number() over() AS rn

     FROM pg_stat_activity p

     WHERE cardinality(pg_blocking_pids(p.pid))= 0

     UNION 

    SELECT   p.datname

           , p.usename

           , p.pid

           , pg_blocking_pids(p.pid) AS blocking_by

           , p.application_name

           , p.wait_event_type

           , p.state

           , p.query_start

           , p.query

           , ( SELECT array_agg(( SELECT relname FROM pg_class pc WHERE pc.oid = pl.relation ))

                 FROM pg_locks pl

                WHERE pl.pid = p.pid

                      AND locktype = 'relation'

             ) AS relation

           , level + 1 as level

           , lt.rn

      FROM pg_stat_activity p

           INNER JOIN lt ON lt.pid = any(pg_blocking_pids(p.pid))

SELECT   p.datname

       , p.usename

       , p.pid

       , p.blocking_by

       , p.application_name

       , p.wait_event_type

       , p.state

       , p.relation

       , now() - p.query_start AS elapsed_time

       , p.query

FROM   ( 

      SELECT   lt.rn

     , lt.level

     , lt.datname

     , lt.usename

     , lt.pid

     , lt.blocking_by

     , lt.application_name

     , lt.wait_event_type

                     , lt.state

                     , lt.relation

                     , lt.query_start

                     , lt.query

                     , count( rn ) over( PARTITION BY rn ) AS blocked_cnt

              FROM lt

       ) AS p

WHERE p.blocked_cnt > 1

ORDER by p.rn, p.level, p.blocking_by

;


1) pg_cancel_backend(pid)            -- current query kill and not disconnect

2) pg_terminate_backend(pid)        -- connection disconnect. 

3) kill -9 process


블로그 이미지

운명을바꾸는자

IT와 함께 살아가는 삶

,