A matching index path that runs in 2 milliseconds can become a tablespace scan after a quiet REBIND. Access path stability on DB2 for z/OS is how you keep known-good plans, detect changes before users feel them, and fall back when a change is bad. This page covers why paths change, plan management (saved package copies), APREUSE and APCOMPARE, and how dynamic SQL fits in.
The optimizer is cost-based. Give it different statistics, a new index, a different clustering ratio, or a new Db2 release behavior, and it may pick a different method, join order, or index. Stability does not mean “never improve.” It means no surprise regressions on the statements that pay the rent. You want:
Static SQL is bound into a package: the path is chosen at BIND/REBIND (unless REOPT re-optimizes at run time). Dynamic SQL is prepared into the statement cache and can change whenever a new prepare occurs. Stability tools differ slightly for each, but the idea is the same: do not let a catalog change overnight turn a nested loop into a merge join on a 200-million-row table without anyone noticing.
Common triggers:
Not every change is bad. A new index that turns a scan into MATCHCOLS = 2 is the point of indexing. Stability processes exist so you see the change, test it, and keep a way back.
Plan management (the PLANMGMT bind option and the PLANMGMT ZPARM) saves extra copies of a package:
After a regression you can REBIND ... SWITCH(PREVIOUS) or SWITCH(ORIGINAL) to activate a saved copy. That is not a new optimization; it is putting the old executable plan back. EXTENDED is the usual subsystem default because the original copy is cheap insurance compared with a production outage.
Plan management also interacts with rebind phase-in (packages that stay executable while a new copy is built). The policy is about how many copies exist and whether you can fall back. It does not by itself freeze the optimizer. Combine it with APREUSE/APCOMPARE when you want freeze or detection.
12345REBIND PACKAGE (HR.EMPPGM.(V1)) PLANMGMT(EXTENDED) EXPLAIN(YES) APCOMPARE(WARN) APREUSE(WARN)
APREUSE tells BIND/REBIND to treat the previous access path as an internal hint and try to generate that same path again. When reuse succeeds, PLAN_TABLE.HINT_USED often shows APREUSE.
Reuse can fail even when you want it: the old index was dropped, SQL changed, or the hint cannot be applied in the new release. WARN then silently accepts a new path unless you also look at messages and PLAN_TABLE. ERROR is the “do not install a new path” switch. APREUSE(ERROR) plus PLANMGMT(EXTENDED) is a common pattern for critical packages: either you keep the old path, or the rebind does not succeed.
Packages bound on very old Db2 levels may need an intermediate bind before APREUSE is supported. Check IBM “reusing and comparing access paths” for your version.
APCOMPARE does not try to force the old path. It compares the newly selected path to the previous one.
Reuse and compare are independent:
Always add EXPLAIN(YES) or EXPLAIN(ONLY) when you compare or reuse, so PLAN_TABLE has the evidence. EXPLAIN(ONLY) is the rehearsal: generate EXPLAIN rows (and test reuse/compare) without replacing the running package the same way a normal REBIND would.
| Option | Meaning |
|---|---|
| PLANMGMT(NONE) | Only the current package copy; no SWITCH to an older path |
| PLANMGMT(BASIC) | Current + previous copy |
| PLANMGMT(EXTENDED) | Current + previous + original; usual default from ZPARM |
| APREUSE(NONE) | Normal optimization; no attempt to reuse |
| APREUSE(WARN) | Try reuse; continue with a new path if reuse fails |
| APREUSE(ERROR) | Try reuse; fail the package if any statement cannot reuse |
| APCOMPARE(WARN) | New paths allowed; mismatches noted (PLAN_TABLE.REMARKS / messages) |
| APCOMPARE(ERROR) | Fail if the new path does not match the old one |
Dynamic statements live in the dynamic statement cache. Same SQL text (and compatible attributes) can reuse a prepared path. RUNSTATS, DDL, and some authorization changes invalidate cache entries. The next PREPARE is a new optimization.
Access path stabilization (dynamic query capture) records a path in catalog tables such as SYSIBM.SYSDYNQRY so matching statements can keep that path even across cache loss. Commands such as START DYNQUERYCAPTURE select statements by monitor criteria. Stabilization is for the high-value dynamic statements you have already proven—not for every ad-hoc QMF query.
Parameter markers and REOPT still matter: a stabilized or cached path that assumed a rare literal can be wrong for a popular one. Stability is not a substitute for representative bind-time values or REOPT when data is extremely skewed.
Optimization hints (OPTHINT, PLAN_TABLE hints, statement-level hints, optimization profiles) pin a path by telling the optimizer what to use. APREUSE is a hint generated from the previous package. Prefer reuse and plan management for “keep what we have.” Use explicit hints when reuse cannot express the path you need, and document them—hints are easy to forget until an index drop makes them fail.
Binding a package is writing a treasure map for how to fetch rows. Sometimes someone redraws the map because the island “looks different” after a storm (new statistics). Plan management keeps photocopies of the old map in a drawer (previous and original). APREUSE says “trace the old map, do not invent a new one.” APCOMPARE says “you may draw a new map, but circle every place it differs.” SWITCH is opening the drawer and using yesterday's map when the new one leads into a swamp.
1. What does PLANMGMT(EXTENDED) keep?
2. What does APREUSE try to do?
3. How is APCOMPARE different from APREUSE?
4. When do access paths commonly change?
5. Why combine EXPLAIN(ONLY) with APREUSE(ERROR)?