统计表膨胀率
目录
统计表膨胀率
WITH bloat AS (
WITH t1 AS (
SELECT
schemaname,
tablename,
( 23 + CEIL ( COUNT ( * ) >> 3 ) ) :: BIGINT nullheader,
MAX ( null_frac ) nullfrac,
CEIL ( SUM ( ( 1 - null_frac ) * avg_width ) ) :: BIGINT datawidth
FROM
pg_stats
--where schemaname='form'
GROUP BY
schemaname,
tablename
),
t2 AS (
SELECT
schemaname,
tablename,
( datawidth + 8 - ( CASE WHEN datawidth % 8 = 0 THEN 8 ELSE datawidth % 8 END ) ) -- avg data len
+ ( 1 - nullfrac ) * 24 + nullfrac * ( nullheader + 8 - ( CASE WHEN nullheader % 8 = 0 THEN 8 ELSE nullheader % 8 END ) ) avgtuplelen
FROM
t1
) SELECT C
.oid,
avgtuplelen
FROM
t2 T,
pg_class C,
pg_namespace n
WHERE
T.schemaname = n.nspname
AND C.relname = T.tablename
AND C.relnamespace = n.oid
AND relpages > 100
and c.relname in
( select relname from (
select relname , reltuples::numeric as 记录数
from pg_class
where relkind = 'r'
)t order by 记录数 desc limit 50)
),
parti AS (
SELECT
parti.inhparent,
parti.inhrelid,
stat.n_dead_tup,
c.relpages,
c.reltuples
FROM
(
SELECT
inhparent,
inhrelid
FROM
pg_inherits inh UNION ALL
( SELECT b.inhparent AS grandpa, A.inhrelid me FROM pg_inherits A INNER JOIN pg_inherits b ON A.inhparent = b.inhrelid )
) AS parti
inner join pg_class c on parti.inhrelid = c.oid
LEFT JOIN pg_stat_user_tables stat ON parti.inhrelid = stat.relid
where c.relname in
( select relname from (
select relname , reltuples::numeric as 记录数
from pg_class
where relkind = 'r'
)t order by 记录数 desc limit 50)
) SELECT
n.nspname "tableSchema",
C.relname "tableName",
'vacuum full '||C.relname||';' "sql",
round(SUM ( pg_total_relation_size ( COALESCE ( parti1.inhrelid, C.oid ) )+0.0 )/1024/1024/1024,2) AS "表大小 GB", --表及其子分区、索引大小,包含索引
round(
SUM ( pg_total_relation_size ( COALESCE ( parti1.inhrelid, C.oid ) ) ) / ( SELECT SUM ( pg_database_size ( datname ) ) AS dbsize FROM pg_database ),
4
) AS "占数据文件比例%",-- 表占数据文件比例
to_char(COALESCE ( MAX ( c.reltuples ), 0 ) + COALESCE ( SUM ( COALESCE ( parti1.reltuples, 0 ) ), 0 ),'9999999999') AS "元组(记录行数)",
CASE
WHEN (coalesce(max( bloat.avgtuplelen), 0) = 0 and coalesce(avg( parti1.avgtuplelen), 0) = 0) or MAX ( COALESCE (c.relpages , 0 ) ) + SUM ( COALESCE ( parti1.relpages, 0 )) = 0 THEN
0 ELSE
round((1 - CEIL ( (MAX ( COALESCE ( c.reltuples, 0 )) + SUM ( COALESCE ( parti1.reltuples, 0 ))) *
(case when max( parti1.avgtuplelen) is not null then AVG( parti1.avgtuplelen) else max ( COALESCE ( bloat.avgtuplelen, 0 ) ) end ) / 8168) /
( MAX ( COALESCE (c.relpages , 0 ) ) + SUM ( COALESCE ( parti1.relpages, 0 )) ))::NUMERIC, 2)*100
END AS "表膨胀率%",
COALESCE ( MAX ( stat.n_dead_tup ), 0 ) + COALESCE ( SUM ( COALESCE ( parti1.n_dead_tup, 0 ) ), 0 ) AS "死元组(行)" --表内死数据行
FROM
pg_class
C INNER JOIN pg_namespace n ON C.relnamespace = n.oid
LEFT JOIN pg_stat_user_tables stat ON C.oid = stat.relid
LEFT JOIN (select p.*, b.* from parti p left join bloat as b ON p.inhrelid = b.oid) as parti1 on c.oid = parti1.inhparent
LEFT JOIN bloat ON C.oid = bloat.oid
WHERE
n.nspname NOT IN ( 'pg_catalog', 'information_schema' )
AND n.nspname !~ '^pg_toast'
AND C.relkind IN ( 'r', 'p' )
AND C.oid NOT IN ( SELECT inhrelid FROM pg_inherits )
and c.relname in
( select relname from (
select relname , reltuples::numeric as 记录数,
'truncate table '||relname||' ;'
from pg_class
where relkind = 'r'
)t order by 记录数 desc limit 50)
GROUP BY
C.relname,
n.nspname
ORDER BY
-- "表大小 GB" DESC
"表膨胀率%" DESC
limit 100