Hello! In our last lesson, we focused on the critical skill of diagnosing production abends, a reactive but essential part of a senior developer's responsibilities. Today, we pivot from fixing failures to preventing performance degradation through proactive, intelligent design. This is where a senior developer's experience truly adds value—by writing code that is not only correct but also efficient from the start.
This lesson addresses how to optimize your COBOL programs by mastering table handling. Specifically, we will cover the crucial differences between SEARCH and SEARCH ALL, the performance implications of OCCURS DEPENDING ON, and other best practices for efficient table access. For interview preparation, these topics are fundamental; they demonstrate a deep understanding of how COBOL's features translate into machine performance, a hallmark of a senior-level practitioner.
The Right Tool for the Job: Sequential vs. Binary Search
At the heart of many COBOL programs lies the need to look up data in a table. COBOL provides two primary verbs for this: SEARCH and SEARCH ALL. Choosing the correct one can be the difference between a program that runs in seconds and one that runs for minutes or hours.
SEARCHperforms a sequential search. It starts at the beginning of the table (or a specified index) and checks each entry one by one until it finds a match or reaches the end.SEARCH ALLperforms a binary search. It requires the table to be pre-sorted and uses a "divide and conquer" strategy to find a match with incredible efficiency.
The following image, though in Portuguese, provides a concise summary of the key differences, which we will explore in detail.

Let's break down this comparison:
| Feature | SEARCH (Sequential) |
SEARCH ALL (Binary) |
|---|---|---|
| Search Mechanism | Sequential (one by one). | Binary (divide and conquer). |
| Performance | Slower, especially for large tables. Performance is . | Extremely fast. Performance is . |
| Data Prerequisite | No sorting required. | Table must be sorted on the key defined in the ASCENDING/DESCENDING KEY clause. |
WHEN Conditions |
Multiple WHEN conditions are allowed. |
Only one WHEN condition is allowed, which must test for equality against the defined key. |
| Index Initialization | You must initialize the index with a SET statement (e.g., SET MY-INDEX TO 1) before the SEARCH. |
The compiler manages the index automatically. You do not initialize it. |
The most important takeaway here is the performance difference. A sequential search of 1,000,000 entries could take up to 1,000,000 comparisons in the worst case. A binary search would take at most 20 comparisons. For a senior developer, this is a non-negotiable optimization for large tables.
The mechanics of SEARCH ALL are based on the classic binary search algorithm. It repeatedly halves the search area until it finds the target.

The prerequisite for SEARCH ALL is strict and a common source of bugs if ignored. You must define the table with an ASCENDING KEY or DESCENDING KEY clause, and the data in the table must be in that order before you execute the search.
WORKING-STORAGE SECTION.
01 STATE-CODE-TABLE.
05 STATE-ENTRIES OCCURS 50 TIMES
ASCENDING KEY IS ST-CODE
INDEXED BY ST-INDEX.
10 ST-CODE PIC XX.
10 ST-NAME PIC X(30).
...
PROCEDURE DIVISION.
...
* Assume STATE-CODE-TABLE is loaded and sorted by ST-CODE.
SEARCH ALL STATE-ENTRIES
AT END
DISPLAY 'STATE NOT FOUND'
WHEN ST-CODE (ST-INDEX) = 'TX'
MOVE ST-NAME (ST-INDEX) TO WS-STATE-NAME
END-SEARCH.
Modern compilers have also heavily optimized the runtime routines for these verbs.
[PDF] Enterprise COBOL for z/OS 6.4 Performance Tuning Guide - IBM
This official IBM guide quantifies the performance benefits of recompiling with modern COBOL versions. We will look specifically at the note on SEARCH ALL.
In the "SEARCH" subsection, please read the short entry on SEARCH ALL. Notice the key takeaway: IBM's own benchmarks show that even the underlying runtime routine for SEARCH ALL is significantly faster in newer compiler versions, reinforcing its importance.
Optimizing Table Structure and Access
Efficiently searching a table is only part of the story. How you define and access the table and its surrounding data structures is equally important.
Indexes and Subscripts
When traversing a table, you can use either an index (USAGE IS INDEX) or a subscript (a regular numeric field, typically COMP/BINARY).
-
USAGE IS INDEX: This is not a number but a displacement (an offset in bytes) from the start of the table. The hardware can use this value directly for address calculation, making it the most efficient method for table access. It is the natural choice when usingSEARCHorPERFORM VARYING... BY. -
USAGE IS COMP/BINARY: If you use a standard data item as a subscript, it must be a binary field for optimal performance. The compiler must first convert aCOMP-3(packed) orDISPLAY(zoned) subscript to binary before it can be used for address calculation, adding significant overhead inside a loop.
[PDF] Performance Tuning with Enterprise COBOL - IBM
This presentation from IBM performance experts provides clear guidance on data type selection. It visually demonstrates the cost of using the wrong data types for computation.
Please review the slide titled "Coding practices Data types" (slide 42). Pay special attention to the bullet points under the Binary section, which explicitly state that indexing/subscripting operations require operands to be converted to binary. Then look at the graph on the next slide, "Coding practices Zoned decimal" (slide 43), which shows the dramatic performance cost of using DISPLAY fields in loops compared to COMP-3 and especially BINARY.
Senior-level Takeaway: Always use USAGE IS INDEX for indexes. If using subscripts, they must be COMP/COMP-4. Using DISPLAY fields as subscripts in performance-critical loops is a major red flag in a code review.
The OCCURS DEPENDING ON Performance Trap
The OCCURS DEPENDING ON (ODO) clause is a powerful feature for handling variable-length data within a record. However, its misuse is one of the most common and severe performance pitfalls in COBOL.
The problem arises from creating variably located data items. When you place a data item within a 01-level record after a table with an ODO clause, the compiler cannot know that item's address at compile time. Its location depends on the actual size of the ODO table at runtime. Therefore, every single access to that variably located item requires extra machine instructions to calculate its address. If this access is inside a loop, the performance penalty is enormous.
Let's look at the guidance from IBM on how to avoid this.
[PDF] Enterprise COBOL for z/OS 6.4 Performance Tuning Guide - IBM
This section of the tuning guide directly addresses the ODO performance issue and provides the standard solution.
Please read the subsection titled "Performance tuning considerations for Occurs Depending On tables". Focus on the explanation of "variably located items" and the simple, effective solution it provides. The benchmark result cited—"94% better" performance—is a powerful justification for this coding standard.
As the guide explains, the solution is simple: structure your data so that no fields follow an ODO table within the same group level.
Bad Practice:
01 BAD-ODO-STRUCTURE.
05 TRANSACTION-COUNT PIC S9(4) COMP.
05 TRANSACTION-TABLE OCCURS 1 TO 100 TIMES
DEPENDING ON TRANSACTION-COUNT.
10 TRAN-ID PIC X(10).
10 TRAN-AMOUNT PIC S9(7)V99 COMP-3.
*-- This field is variably located. Accessing it is SLOW.
05 BATCH-TOTAL PIC S9(9)V99 COMP-3.
Best Practice:
01 GOOD-ODO-TABLE.
05 TRANSACTION-COUNT PIC S9(4) COMP.
05 TRANSACTION-TABLE OCCURS 1 TO 100 TIMES
DEPENDING ON TRANSACTION-COUNT.
10 TRAN-ID PIC X(10).
10 TRAN-AMOUNT PIC S9(7)V99 COMP-3.
01 BATCH-VARIABLES.
*-- This field now has a fixed, known location. Access is FAST.
05 BATCH-TOTAL PIC S9(9)V99 COMP-3.
In an interview, being able to describe this specific problem and its solution demonstrates a sophisticated understanding of COBOL performance that goes beyond basic syntax.
Conclusion
We've moved from reactive debugging to proactive optimization, focusing on the high-impact area of table handling. Writing efficient code is a critical differentiator for a senior developer, and the techniques we've covered are fundamental to achieving that goal.
Key Takeaways:
SEARCHvs.SEARCH ALL: UseSEARCH ALLfor any large, sorted table to leverage the exponential speed of a binary search. Understand its strict prerequisites.- Efficient Table Access: Use
USAGE IS INDEXfor indexes andCOMP(BINARY) for subscripts to avoid costly data type conversions during address calculations. OCCURS DEPENDING ON: Avoid the "variably located item" performance trap by ensuring ODO tables are the last item in their containing group, or by placing them in their own01-level record.
In our next lesson, we will broaden our scope from micro-optimizations to program architecture. We will tackle a common senior-level task: refactoring a monolithic COBOL program by extracting a section into a callable subprogram, a key skill for improving modularity, maintainability, and reusability in legacy systems.