MainframeDatabaseDB2 Complete Reference

DB2 JCL Utilities: RUNSTATS, REORG, COPY, RECOVER Complete Guide

TT
TopicTrick Team
DB2 JCL Utilities: RUNSTATS, REORG, COPY, RECOVER Complete Guide

DB2 JCL Utilities: Complete Reference Guide

DB2 for z/OS maintenance is driven by a suite of batch utilities invoked through JCL. Unlike DB2 LUW where you issue maintenance commands from a CLI, DB2 z/OS utilities are batch programs submitted as jobs to JES. They handle everything from statistics collection and reorganisation to backup, recovery, and bulk data loading.

This guide covers every DBA and developer must-know utility with complete, production-ready JCL examples.


Utility Overview

All DB2 utilities share the same JCL skeleton: they execute DSNUTILB (or a related program) with the subsystem name, and read utility control statements from a SYSIN DD:

jcl
//UTILSTEP EXEC PGM=DSNUTILB,PARM='DSN1,UTILNAME'
//STEPLIB  DD DSN=DSN.SDSNEXIT,DISP=SHR
//         DD DSN=DSN.SDSNLOAD,DISP=SHR
//SYSPRINT DD SYSOUT=*
//UTPRINT  DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
//SYSIN    DD *
  utility-control-statements
/*

The PARM value has the format 'subsystem-id,utility-name'. STEPLIB must include the DB2 load libraries.


RUNSTATS — Collecting Optimizer Statistics

RUNSTATS collects statistical information about tables and indexes and stores it in the DB2 catalog. The query optimizer uses these statistics to choose access paths. Stale statistics are one of the leading causes of poor DB2 query performance.

Basic RUNSTATS on a Tablespace

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)
    SHRLEVEL CHANGE
/*

RUNSTATS with Column Statistics

For complex queries with range predicates, collect column-level statistics:

jcl
//SYSIN    DD *
  RUNSTATS TABLESPACE EMPDB.EMPTS01
    TABLE(EMPSCHM.EMPLOYEE
        COLUMN(WORKDEPT, SALARY, HIREDATE)
        COLGROUP(WORKDEPT, JOB)
    )
    INDEX(ALL KEYCARD)
    SHRLEVEL CHANGE
    REPORT YES
/*

COLGROUP collects statistics on combinations of columns — valuable for multi-column predicates. REPORT YES generates a report of the statistics collected.


REORG — Reorganising Tablespaces and Indexes

As rows are inserted, updated, and deleted, DB2 tablespaces become fragmented. Free space accumulates in random locations, and if clustering is defined on an index, the physical row order drifts from the logical order. REORG reclaims this space and restores order.

REORG TABLESPACE — Online (SHRLEVEL CHANGE)

jcl
//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))
//SYSUT1   DD UNIT=SYSDA,SPACE=(CYL,(500,200))
//SYSIN    DD *
  REORG TABLESPACE EMPDB.EMPTS01
    SHRLEVEL CHANGE
    DEADLINE NONE
    SORTDEVT SYSDA
    SORTNUM 4
/*

SHRLEVEL CHANGE keeps the tablespace available throughout. DB2 REORGs in three phases: unload → reload → switch. During the switch phase (seconds), exclusive access is taken briefly.

REORG with DISCARD

jcl
//SYSIN    DD *
  REORG TABLESPACE EMPDB.EMPTS01
    SHRLEVEL CHANGE
    DISCARD DD(DSCARD)
    MAPPINGTABLE EMPSCHM.REORG_MAP
/*

DISCARD allows rows matching a filter to be removed during reorganisation.

REORG INDEX

jcl
//SYSIN    DD *
  REORG INDEX EMPSCHM.EMPNO_IDX
    SHRLEVEL CHANGE
/*

COPY — Image Backup

COPY creates an image copy — a backup — of a tablespace or index space. DB2 recovery depends on image copies combined with log records.

Full Image Copy

jcl
//COPY     EXEC PGM=DSNUTILB,PARM='DSN1,COPY'
//STEPLIB  DD DSN=DSN.SDSNEXIT,DISP=SHR
//         DD DSN=DSN.SDSNLOAD,DISP=SHR
//SYSPRINT DD SYSOUT=*
//SYSCOPY  DD DSN=BACKUP.EMPDB.EMPTS01.FULL,
//            DISP=(NEW,CATLG),
//            UNIT=TAPE,
//            SPACE=(CYL,(100,50))
//SYSIN    DD *
  COPY TABLESPACE EMPDB.EMPTS01
    FULL YES
    SHRLEVEL CHANGE
    COPY1
/*

Incremental Image Copy

An incremental copy captures only pages changed since the last full copy — much faster for large tablespaces:

jcl
//SYSIN    DD *
  COPY TABLESPACE EMPDB.EMPTS01
    FULL NO
    SHRLEVEL CHANGE
/*

Copy to Two Targets Simultaneously

DB2 supports writing to a primary and local backup simultaneously:

jcl
//SYSCOPY  DD DSN=BACKUP.EMPDB.EMPTS01.FULL.PRI,...
//SYSCOPY2 DD DSN=BACKUP.EMPDB.EMPTS01.FULL.SEC,...
//SYSIN    DD *
  COPY TABLESPACE EMPDB.EMPTS01
    FULL YES
    COPYDDN(SYSCOPY,SYSCOPY2)
    SHRLEVEL CHANGE
/*

RECOVER — Restoring from Backup

RECOVER restores a tablespace to a consistent state using image copies and log records.

Recover to Current

jcl
//RECOVER  EXEC PGM=DSNUTILB,PARM='DSN1,RECOVER'
//STEPLIB  DD DSN=DSN.SDSNEXIT,DISP=SHR
//         DD DSN=DSN.SDSNLOAD,DISP=SHR
//SYSPRINT DD SYSOUT=*
//SYSIN    DD *
  RECOVER TABLESPACE EMPDB.EMPTS01
/*

DB2 locates the most recent image copy from the bootstrap dataset (BSDS) and applies all log records up to the current end of log.

Recover to a Point in Time

jcl
//SYSIN    DD *
  RECOVER TABLESPACE EMPDB.EMPTS01
    TORBA X'000000A1B2C3D4'
/*

TORBA (To Recovery Log Byte Address) recovers to a specific point in the log. TOTIME '2026-04-20-14.30.00' can also specify a timestamp.


CHECK DATA — Referential Integrity Validation

After a recovery or bulk load, CHECK DATA verifies referential integrity:

jcl
//CHKDATA  EXEC PGM=DSNUTILB,PARM='DSN1,CHECK'
//STEPLIB  DD DSN=DSN.SDSNEXIT,DISP=SHR
//         DD DSN=DSN.SDSNLOAD,DISP=SHR
//SYSPRINT DD SYSOUT=*
//SYSIN    DD *
  CHECK DATA TABLESPACE EMPDB.EMPTS01
    SCOPE ALL
    LOBERROR REPORT
/*

LOAD — Bulk Data Loading

LOAD is the fastest way to insert large volumes of data:

jcl
//LOAD     EXEC PGM=DSNUTILB,PARM='DSN1,LOAD'
//STEPLIB  DD DSN=DSN.SDSNEXIT,DISP=SHR
//         DD DSN=DSN.SDSNLOAD,DISP=SHR
//SYSPRINT DD SYSOUT=*
//SYSREC   DD DSN=INPUT.EMPLOYEE.DATA,DISP=SHR
//SYSERR   DD SYSOUT=*
//SORTOUT  DD UNIT=SYSDA,SPACE=(CYL,(200,100))
//SYSIN    DD *
  LOAD DATA INDDN(SYSREC)
    INTO TABLE EMPSCHM.EMPLOYEE
    (EMPNO    POSITION(1:6)    CHAR(6),
     FIRSTNME POSITION(7:18)   CHAR(12),
     MIDINIT  POSITION(19:19)  CHAR(1),
     LASTNAME POSITION(20:34)  CHAR(15),
     WORKDEPT POSITION(35:37)  CHAR(3),
     SALARY   POSITION(38:46)  DECIMAL EXTERNAL(9))
    RESUME YES
    SHRLEVEL CHANGE
/*

RESUME YES appends to existing data. REPLACE deletes existing rows before loading.


UNLOAD — Extracting Data

UNLOAD extracts data from DB2 tablespaces to sequential datasets:

jcl
//UNLOAD   EXEC PGM=DSNUTILB,PARM='DSN1,UNLOAD'
//STEPLIB  DD DSN=DSN.SDSNEXIT,DISP=SHR
//         DD DSN=DSN.SDSNLOAD,DISP=SHR
//SYSPRINT DD SYSOUT=*
//SYSREC   DD DSN=EXTRACT.EMPLOYEE.DATA,
//            DISP=(NEW,CATLG),
//            UNIT=SYSDA,
//            SPACE=(CYL,(50,25))
//SYSIN    DD *
  UNLOAD TABLESPACE EMPDB.EMPTS01
    FROM TABLE EMPSCHM.EMPLOYEE
    (EMPNO, FIRSTNAME, LASTNAME, WORKDEPT, SALARY)
    WHERE SALARY > 50000
/*

REBIND — Refreshing Package Access Plans

When statistics change significantly after RUNSTATS, existing packages may still use the old access plan. REBIND forces DB2 to recompile access plans:

jcl
//REBIND   EXEC PGM=IKJEFT01
//STEPLIB  DD DSN=DSN.SDSNEXIT,DISP=SHR
//         DD DSN=DSN.SDSNLOAD,DISP=SHR
//SYSPRINT DD SYSOUT=*
//SYSTSPRT DD SYSOUT=*
//SYSTSIN  DD *
  DSN SYSTEM(DSN1)
  REBIND PACKAGE(EMPPROJ.EMPRPT(1))
  END
/*

A typical maintenance sequence for a tablespace is: RUNSTATS → REBIND → (if needed) REORG → COPY.


Maintenance Schedule Best Practices

A well-run DB2 shop follows a maintenance cycle:

Daily: Check for tablespaces in RECP (Recovery Pending) or RBDP (Rebuild Pending) status.

Weekly: RUNSTATS on volatile tablespaces; REBIND packages with outdated access plans; incremental COPY.

Monthly: Full COPY; REORG on tablespaces with REORGCHK indicators; CHECK INDEX on large indexes.

After bulk operations: RUNSTATS immediately after any LOAD or mass INSERT/DELETE/UPDATE affecting > 10% of rows.


Next Steps

With JCL utilities mastered, you can maintain DB2 z/OS databases at a professional level. The next critical mainframe DB2 skill is embedding SQL directly in COBOL programs. See DB2 COBOL Embedded SQL for a complete guide. For the full learning path, visit the DB2 Mastery course hub.


Monitoring Utility Status

Check the status of running or pending utilities:

text
-DSN1 DISPLAY UTILITY(*)

This shows all active and recent utilities, their phase, and percentage complete. To terminate a stuck utility:

text
-DSN1 TERM UTILITY(utility-id)

Check tablespace status with:

text
-DSN1 DISPLAY DATABASE(EMPDB) SPACE(*) RESTRICT

Look for RO (Read Only), STOP, RECP (Recovery Pending), or RBDP (Rebuild Pending) status codes, which indicate the tablespace needs attention.


CHECK INDEX — Index Integrity

After a RECOVER or hardware issue, indexes may be inconsistent with the data. CHECK INDEX verifies consistency:

jcl
//CHKIDX   EXEC PGM=DSNUTILB,PARM='DSN1,CHECK'
//STEPLIB  DD DSN=DSN.SDSNEXIT,DISP=SHR
//         DD DSN=DSN.SDSNLOAD,DISP=SHR
//SYSPRINT DD SYSOUT=*
//SYSIN    DD *
  CHECK INDEX ALL TABLESPACE EMPDB.EMPTS01
/*

If CHECK INDEX finds errors, the index space enters RBDP (Rebuild Pending) status. Run REBUILD INDEX to fix it:

jcl
//SYSIN    DD *
  REBUILD INDEX (ALL) TABLESPACE EMPDB.EMPTS01
    SHRLEVEL CHANGE
/*

MODIFY RECOVERY — Housekeeping the SYSIBM.SYSCOPY Catalog

Over time, the SYSIBM.SYSCOPY table accumulates records from old image copies. MODIFY RECOVERY prunes old entries:

jcl
//MODREC   EXEC PGM=DSNUTILB,PARM='DSN1,MODIFY'
//STEPLIB  DD DSN=DSN.SDSNEXIT,DISP=SHR
//         DD DSN=DSN.SDSNLOAD,DISP=SHR
//SYSPRINT DD SYSOUT=*
//SYSIN    DD *
  MODIFY RECOVERY TABLESPACE EMPDB.EMPTS01
    DELETE AGE(30)
/*

This removes recovery history records older than 30 days, keeping the SYSCOPY table manageable. Always ensure you have at least one full image copy retained before pruning.