-- =============================================================================
-- Script Name : pdb_growth_report.sql
-- Purpose : PDB-safe Database Growth Report (User-defined day range)
-- Author : Raunak
-- Sections : [1] Total DB Growth, [2] Tablespace Growth, [3] Segment Growth
-- Output : Timestamped spool file (e.g., db_growth_report_2025_06_30_1930.txt)
-- =============================================================================
-- === Prompt for number of days ===
ACCEPT days NUMBER PROMPT 'Enter number of days to analyze (e.g., 7, 30, 60): '
-- === Create timestamped spool file ===
COLUMN dt NEW_VALUE file_time NOPRINT
SELECT TO_CHAR(SYSDATE, 'YYYY_MM_DD_HH24MI') dt FROM dual;
SPOOL db_growth_report_&&file_time..txt
-- === SQL*Plus display formatting ===
SET LINESIZE 200
SET PAGESIZE 100
SET FEEDBACK OFF
SET TRIMSPOOL ON
-- === Column formatting ===
COLUMN start_time FORMAT A30
COLUMN end_time FORMAT A30
COLUMN first_seen FORMAT A30
COLUMN last_seen FORMAT A30
COLUMN total_db_growth_gb FORMAT 9999.99
COLUMN tablespace_id FORMAT 999
COLUMN tablespace_name FORMAT A25
COLUMN growth_gb FORMAT 9999.99
COLUMN owner FORMAT A15
COLUMN object_name FORMAT A25
COLUMN subobject_name FORMAT A20
COLUMN object_type FORMAT A15
COLUMN growth_mb FORMAT 999999.99
COLUMN instance_number FORMAT 999
-- =============================================================================
PROMPT
PROMPT === [1] Total Database Growth Over Last &days Days ===
-- =============================================================================
SELECT
TO_CHAR(MIN(snap.begin_interval_time), 'DD-MON-YY HH24:MI') AS start_time,
TO_CHAR(MAX(snap.end_interval_time), 'DD-MON-YY HH24:MI') AS end_time,
ROUND(MAX(x.used_gb) - MIN(x.used_gb), 2) AS total_db_growth_gb
FROM (
SELECT
tsu.snap_id,
SUM(tsu.tablespace_usedsize) * 8192 / 1024 / 1024 / 1024 AS used_gb
FROM
dba_hist_tbspc_space_usage tsu
JOIN dba_hist_snapshot snap ON tsu.snap_id = snap.snap_id
WHERE
snap.begin_interval_time >= SYSDATE - &days
GROUP BY
tsu.snap_id
) x
JOIN dba_hist_snapshot snap ON snap.snap_id = x.snap_id;
-- =============================================================================
PROMPT
PROMPT === [2] Tablespace-wise Growth Over Last &days Days ===
-- =============================================================================
SELECT
tsu.tablespace_id,
TO_CHAR(MIN(snap.begin_interval_time), 'DD-MON-YY HH24:MI') AS start_time,
TO_CHAR(MAX(snap.end_interval_time), 'DD-MON-YY HH24:MI') AS end_time,
ROUND((MAX(tsu.tablespace_usedsize) - MIN(tsu.tablespace_usedsize)) * 8192 / 1024 / 1024 / 1024, 2) AS growth_gb
FROM
dba_hist_tbspc_space_usage tsu
JOIN dba_hist_snapshot snap ON tsu.snap_id = snap.snap_id
WHERE
snap.begin_interval_time >= SYSDATE - &days
GROUP BY
tsu.tablespace_id
HAVING
(MAX(tsu.tablespace_usedsize) - MIN(tsu.tablespace_usedsize)) > 0
ORDER BY
growth_gb DESC;
-- =============================================================================
PROMPT
PROMPT === [3] Top Growing Segments Over Last &days Days ===
-- =============================================================================
SELECT
obj.owner,
obj.object_name,
obj.subobject_name,
obj.object_type,
ROUND(SUM(ss.space_used_delta) * 8 / 1024, 2) AS growth_mb,
TO_CHAR(MIN(snap.begin_interval_time), 'DD-MON-YY HH24:MI') AS first_seen,
TO_CHAR(MAX(snap.end_interval_time), 'DD-MON-YY HH24:MI') AS last_seen,
snap.instance_number
FROM
dba_hist_seg_stat ss
JOIN dba_hist_seg_stat_obj obj ON ss.obj# = obj.obj#
JOIN dba_hist_snapshot snap ON ss.snap_id = snap.snap_id
WHERE
snap.begin_interval_time >= SYSDATE - &days
GROUP BY
obj.owner, obj.object_name, obj.subobject_name, obj.object_type, snap.instance_number
HAVING
SUM(ss.space_used_delta) > 0
ORDER BY
growth_mb DESC
FETCH FIRST 15 ROWS ONLY;
-- === End spool ===
SPOOL OFF
PROMPT
PROMPT Report successfully written to: db_growth_report_&&file_time..txt