DB2 RUNSTATS and REORG: Complete Maintenance Guide with JCL Examples

DB2 RUNSTATS and REORG: Complete Maintenance Guide
Database maintenance is not optional — it is the difference between a DB2 system that stays fast over years of operation and one that slowly degrades until queries that once ran in seconds start taking minutes. Two utilities drive the core of DB2 maintenance: RUNSTATS (statistics collection) and REORG (physical reorganisation). This guide covers both in depth for DB2 LUW and DB2 for z/OS.
Why Statistics and Reorganisation Matter
The Role of Statistics
The DB2 optimizer chooses query access paths based on statistics stored in the catalog — information about table cardinalities, column value distributions, index clustering ratios, and page counts. When data changes significantly after the last RUNSTATS run, these statistics become outdated. The optimizer may then choose a suboptimal access path — for example, opting for a tablespace scan when a highly selective index exists, because outdated statistics suggest the index is less selective than it actually is.
The Role of Reorganisation
As rows are inserted, updated, and deleted, the physical layout of data in a tablespace degrades:
- Free space fragments: Deleted rows leave gaps scattered throughout pages
- Page splits: Index leaf pages split, creating disorganised trees
- Clustering degrades: New rows for a clustering index key range are inserted wherever space is found rather than in order
REORG physically rebuilds the tablespace and indexes, restoring optimal layout.
RUNSTATS — DB2 LUW
Basic RUNSTATS Command
# Connect to the database
db2 CONNECT TO mydb
# Run statistics on a specific table
db2 RUNSTATS ON TABLE empschm.employee WITH DISTRIBUTION AND DETAILED INDEXES ALL
# Run on all tables in a schema
db2 "SELECT 'RUNSTATS ON TABLE ' || RTRIM(TABSCHEMA) || '.' || TABNAME
|| ' WITH DISTRIBUTION AND DETAILED INDEXES ALL;'
FROM SYSCAT.TABLES WHERE TABSCHEMA = 'EMPSCHM' AND TYPE = 'T'" > runstats.sql
db2 -tf runstats.sqlRUNSTATS Options
# Basic table statistics only
db2 RUNSTATS ON TABLE empschm.employee
# With column distribution statistics (needed for range predicates)
db2 RUNSTATS ON TABLE empschm.employee WITH DISTRIBUTION
# With index statistics
db2 RUNSTATS ON TABLE empschm.employee AND INDEXES ALL
# Full statistics — recommended
db2 RUNSTATS ON TABLE empschm.employee WITH DISTRIBUTION AND DETAILED INDEXES ALL
# On specific columns and indexes
db2 "RUNSTATS ON TABLE empschm.employee ON COLUMNS(workdept, salary, hiredate)
AND DETAILED INDEXES ALL"Automatic Statistics Collection (DB2 LUW)
DB2 LUW can collect statistics automatically via the Auto Stats Maintenance feature:
# Enable auto stats
db2 UPDATE DB CFG FOR mydb USING AUTO_MAINT ON AUTO_TBL_MAINT ON AUTO_RUNSTATS ONAuto RUNSTATS analyses statistics staleness and triggers collection when needed, based on the percentage of rows changed since the last collection.
RUNSTATS — DB2 for z/OS (JCL)
Comprehensive RUNSTATS JCL
//RUNSTATS EXEC PGM=DSNUTILB,PARM='DSN1,RUNSTATS'
//STEPLIB DD DSN=DSN.SDSNEXIT,DISP=SHR
// DD DSN=DSN.SDSNLOAD,DISP=SHR
//SYSPRINT DD SYSOUT=*
//UTPRINT DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
//SYSIN DD *
RUNSTATS TABLESPACE EMPDB.EMPTS01
TABLE(ALL)
INDEX(ALL KEYCARD)
SHRLEVEL CHANGE
UPDATE ALL
REPORT YES
/*Key options:
TABLE(ALL)— collect statistics on all tables in the tablespaceINDEX(ALL KEYCARD)— collect key cardinality statistics on all indexesSHRLEVEL CHANGE— run online (no outage)UPDATE ALL— update both table and index statisticsREPORT YES— generate a statistics report in SYSPRINT
RUNSTATS with Column Groups
For predicates on multiple columns:
//SYSIN DD *
RUNSTATS TABLESPACE EMPDB.EMPTS01
TABLE(EMPSCHM.EMPLOYEE
COLUMN(WORKDEPT, SALARY, HIREDATE, JOB)
COLGROUP(WORKDEPT, JOB)
COLGROUP(WORKDEPT, HIREDATE)
)
INDEX(ALL KEYCARD)
SHRLEVEL CHANGE
/*Column group statistics help the optimizer estimate selectivity for multi-column predicates more accurately.
REORGCHK — DB2 LUW
Before running REORG, use REORGCHK to determine whether it is actually needed:
# Check with current statistics
db2 REORGCHK CURRENT STATISTICS ON TABLE empschm.employee
# Collect fresh statistics first, then check
db2 REORGCHK UPDATE STATISTICS ON TABLE empschm.employee
# Check all tables in a schema
db2 REORGCHK UPDATE STATISTICS ON SCHEMA empschmSample REORGCHK output:
Table: EMPSCHM.EMPLOYEE
CARD OV NP FP ACTBLK TBL F1 F2 F3
12345 0 8 2 105 N - - *
* indicates REORG is recommended for formula F3The asterisk next to F3 means the table has excessive overflow rows and needs REORG.
REORG — DB2 LUW
Online REORG (Recommended)
# Online REORG — table stays available
db2 REORG TABLE empschm.employee INPLACE
# With index rebuild
db2 REORG TABLE empschm.employee INPLACE ALLOW WRITE ACCESS
# Offline REORG (faster, but table unavailable)
db2 REORG TABLE empschm.employee
# REORG a specific index
db2 REORG INDEXES ALL FOR TABLE empschm.employeeChecking REORG Status
# Monitor REORG progress
db2pd -reorg -db mydbREORG — DB2 for z/OS (JCL)
Online REORG with SHRLEVEL CHANGE
//REORG EXEC PGM=DSNUTILB,PARM='DSN1,REORG'
//STEPLIB DD DSN=DSN.SDSNEXIT,DISP=SHR
// DD DSN=DSN.SDSNLOAD,DISP=SHR
//SYSPRINT DD SYSOUT=*
//UTPRINT DD SYSOUT=*
//SORTOUT DD UNIT=SYSDA,SPACE=(CYL,(500,200),RLSE)
//SYSUT1 DD UNIT=SYSDA,SPACE=(CYL,(500,200),RLSE)
//SYSIN DD *
REORG TABLESPACE EMPDB.EMPTS01
SHRLEVEL CHANGE
DEADLINE NONE
SORTDEVT SYSDA
SORTNUM 6
LOG YES
/*REORG with Space Parameters
//SYSIN DD *
REORG TABLESPACE EMPDB.EMPTS01
SHRLEVEL CHANGE
FREEPAGE 5
PCTFREE 10
DEADLINE NONE
/*FREEPAGE 5 leaves every 5th page empty for future inserts. PCTFREE 10 leaves 10% free space on each page.
REORG Index
//SYSIN DD *
REORG INDEX EMPSCHM.EMP_DEPT_IDX
SHRLEVEL CHANGE
/*Recommended Maintenance Workflow
The optimal maintenance sequence for DB2 is:
1. COPY (image copy — backup before maintenance)
2. REORG (reorganise if needed based on REORGCHK)
3. RUNSTATS (collect fresh statistics on reorganised data)
4. REBIND (apply updated statistics to package access plans)
5. COPY (post-maintenance image copy)Always take an image copy before REORG. If REORG fails partway through, recovery requires the pre-REORG image copy.
Maintenance JCL Procedure (Combined)
//MAINT PROC DB2SSID=DSN1,DBNAME=EMPDB,TSNAME=EMPTS01
//COPY1 EXEC PGM=DSNUTILB,PARM='&DB2SSID,COPY'
//SYSIN DD *
COPY TABLESPACE &DBNAME..&TSNAME FULL YES SHRLEVEL CHANGE
/*
//REORG1 EXEC PGM=DSNUTILB,PARM='&DB2SSID,REORG'
//SYSIN DD *
REORG TABLESPACE &DBNAME..&TSNAME SHRLEVEL CHANGE
/*
//STATS1 EXEC PGM=DSNUTILB,PARM='&DB2SSID,RUNSTATS'
//SYSIN DD *
RUNSTATS TABLESPACE &DBNAME..&TSNAME TABLE(ALL) INDEX(ALL KEYCARD)
SHRLEVEL CHANGE UPDATE ALL
/*
// PENDAutomating Maintenance
On DB2 LUW, wrap maintenance in a shell script scheduled with cron:
#\!/bin/bash
# Weekly DB2 maintenance script
DB=mydb
db2 CONNECT TO $DB
# Collect stats and check if REORG needed
for table in $(db2 "SELECT RTRIM(TABSCHEMA)||'.'||TABNAME FROM SYSCAT.TABLES WHERE TABSCHEMA='EMPSCHM' AND TYPE='T'" | grep EMPSCHM); do
echo "Processing $table"
db2 "RUNSTATS ON TABLE $table WITH DISTRIBUTION AND DETAILED INDEXES ALL"
db2 "REORG TABLE $table INPLACE"
done
db2 CONNECT RESETNext Steps
With statistics and reorganisation under control, your DB2 environment will maintain peak performance over time. The next topic covers protecting your data with backup and recovery strategies. Read the DB2 Backup and Recovery guide. For the full DB2 learning path, visit the DB2 Mastery course hub.
