TABLE lookup feels free on ten test records. Production tells a different story: two hundred thousand payroll rows, fourteen decode tables per row, three million SEARCH calls before the first PRINT buffer fills. Memory reservation too tight aborts at initiation; too loose wastes region other steps need. Legacy GET-loop lookups that survived decades suddenly miss batch windows when input files double. This page teaches table performance for beginners and maintainers: how memory scales with max-entries and DESC width, why binary search is rarely the bottleneck, multiplicative cost when SEARCH runs inside tight JOB loops, consolidating tables versus splitting them, INSTREAM versus external load trade-offs, diagnosing CPU spikes after reference file growth, and when to graduate from TABLE to SQL FILE. The goal is predictable batch elapsed time without sacrificing readable decoded reports.
Table performance splits into three phases: load, lookup, and maintenance overhead outside Easytrieve. Load happens once per run for external tables or once at compile for INSTREAM. Lookup happens per SEARCH call—cheap individually, expensive in aggregate. Maintenance—sorting reference files, validating order, recompiling INSTREAM—is human and JCL time but prevents lookup failures that cause reruns. Tuning focuses on load memory and lookup multiplication.
Approximate each row as ARG bytes plus DESC bytes plus small overhead. Multiply by row count reserved in max-entries. Sum across all TABLE files in the program. A program with eight external tables at five thousand rows each, fifty-byte average row payload, sits near two megabytes of table data before stacks and buffers—usually fine. The same pattern with five hundred thousand rows per table is not a TABLE problem—it is a SQL problem.
| Factor | Impact | Tuning action |
|---|---|---|
| Row count | Linear memory growth | Right-size max-entries; avoid huge tables in memory |
| DESC width | Bytes per row | Store only print-needed text; trim padded maintenance |
| Table count | Sum of all tables | Consolidate decodes sharing load lifecycle |
| Multiple programs | Each job loads independently | Share SQL reference for very large data |
Binary search on ten thousand rows is at most fourteen compares. Multiply fourteen by three million SEARCH calls and CPU matters. Profile mentally: input records times SEARCH calls per record times log(table size). Reducing calls per record dominates reducing table size when row counts stay in thousands. A program searching twelve tables per employee should ask whether all twelve are needed on every row or only for subsets filtered by IF earlier in JOB logic.
12345678JOB INPUT PAYROLL IF DEPT GT 0 SEARCH DEPTTAB WITH DEPT GIVING DEPT-NAME END-IF IF PLAN-CODE NE ' ' SEARCH PLANTAB WITH PLAN-CODE GIVING PLAN-NAME END-IF PRINT PAYRPT
Guard expensive lookups behind conditions so zero-department rows skip DEPTTAB SEARCH entirely. Apply same pattern for optional codes, terminated employees, or records failing earlier validation.
| Aspect | INSTREAM | External TABLE |
|---|---|---|
| Initiation load time | None—prebuilt | Sequential read of maintenance file |
| Change latency | Recompile required | Replace file and rerun |
| Memory | In load module | Reserved at initiation |
| Best size | Small static | Medium, changing |
Replacing TABLE SEARCH with per-record reference GET can increase CPU orders of magnitude—see Sequential search tutorial. Performance remediation often starts by converting GET-loop decodes to FILE TABLE. Measure elapsed time before and after on representative production file sizes, not ten-row test decks.
Storage abends at JOB start after adding large external tables usually mean undersized REGION or sum of tables exceeding available memory. Increase JCL REGION, reduce max-entries realism, shrink DESC, or move largest table to SQL. Initiation load is synchronous—no SEARCH runs until load completes successfully.
TABLE lookup itself avoids disk per SEARCH after load. DISPLAY on every matched row floods SYSPRINT. WRITE exception records for bad keys are appropriate; logging every successful decode is not. Exception paths should be low volume—if half of rows trigger IF NOT, fix reference data instead of tuning SEARCH.
Graduate to SQL FILE with indexed Db2 columns. Keep small static decodes in TABLE for speed and simplicity; centralize large shared reference in database.
Table performance is not making each dictionary lookup super fast—it is not asking the dictionary a million questions when you only need a few, and not carrying twenty heavy dictionaries in your backpack when one combined book would do. Easytrieve looks up words quickly; your job design decides how many times you ask.
1. Primary CPU risk with TABLE lookup is:
2. Undersized max-entries causes:
3. Best way to reduce twelve SEARCH calls per input row:
4. INSTREAM tables save runtime load but:
5. Large DESC fields mainly affect: