VSAM uses buffer pools to hold control intervals (CIs) in memory. Data CIs from the data component are held in data buffers; index CIs from the index component (KSDS) are held in index buffers. The number of data buffers (BUFND) and index buffers (BUFNI) affects how much data and index can be cached and therefore how many physical I/Os are needed. For sequential processing, having more data buffers often improves throughput; for random access by key, having enough index buffers reduces index I/O. This page explains buffer pool management in VSAM: what BUFND and BUFNI are, how they affect sequential and random access, and how to specify them (e.g. via the JCL AMP parameter).
When VSAM reads a control interval from disk, it places it in a buffer in memory. The buffer pool is the set of buffers allocated for that file. For a KSDS there are two pools: one for the data component (data buffers) and one for the index component (index buffers). For ESDS, RRDS, or LDS there is only the data component, so only data buffers apply. The size of each buffer is the control interval size (CISZ)—one buffer holds one CI. So if you have 10 data buffers and a 4KB CI, you have 40KB of buffer space for data CIs. The access method uses these buffers to satisfy READ requests: if the CI that contains the requested record is already in a buffer, no disk I/O is needed; if not, it reads the CI into a buffer (possibly replacing another CI) and then returns the record.
BUFND is the number of data buffers (control interval buffers for the data component). BUFNI is the number of index buffers (for the index component, KSDS only). You can specify them when opening the file: in JCL via the AMP (Access Method Parameters) parameter on the DD statement, or in the program via the ACB (Access Control Block). If you do not specify them, the system uses defaults. The defaults may be adequate for small files or light use but are often too low for good sequential or random performance. Tuning BUFND and BUFNI for your workload can significantly reduce I/O and improve elapsed time.
| Parameter | Meaning |
|---|---|
| BUFND | Number of data buffers. Each buffer holds one control interval (CI) from the data component. More buffers allow more CIs to be in memory; useful for sequential processing and for holding recently used CIs for random access. |
| BUFNI | Number of index buffers (KSDS only). Each buffer holds one index CI. For key-based access, VSAM reads index levels to find the data CI; enough index buffers (e.g. at least one per index level plus some extra) reduce index I/O. |
| BUFSP | Total buffer space in bytes. Sometimes used instead of or with BUFND/BUFNI to allocate a pool of a given size; the system may derive the number of buffers from the pool size and CI size. |
For sequential processing, the program reads records in order. VSAM reads CIs in order from the data component. If you have enough data buffers to hold at least one full control area (CA)—that is, all CIs in one CA—then once a CA is read, the next several reads can be satisfied from the buffer pool without additional I/O. So for sequential access, a higher BUFND is usually better. A common guideline is to set BUFND to at least the number of CIs per control area plus one, or to a value that allows reading a full CA (or more) into memory. That way, sequential reads are served from the buffer pool. BUFNI can stay relatively low (e.g. 2–3) for pure sequential access because the index is used mainly at the start for positioning; most I/O is data.
For random access by key, the access method must traverse the index (index set and sequence set) to find the data CI that contains the record. Each level of the index may require reading an index CI. If those index CIs are not in the buffer pool, each level causes an I/O. So for random access, having enough index buffers (BUFNI) is important. A minimum is one buffer per index level (so that the top-level index CI, the next-level CIs, and the sequence set CIs can be held). In practice, BUFNI is often set higher so that multiple index CIs at each level can be cached, reducing I/O when many random reads hit different parts of the index. BUFND for random access does not need to be as high as for sequential; you may need only one or a few data CIs at a time, but having a few data buffers still helps when the same CI is accessed again or when doing a short sequence of reads in the same CI.
| Access type | Buffer recommendation |
|---|---|
| Sequential | Use higher BUFND (e.g. number of CIs per control area plus one, or more). Low BUFNI is often enough (e.g. 2–3) since index is used mainly for positioning. |
| Random (by key) | Use enough BUFNI to hold index levels (at least one buffer per level, often more). BUFND can be moderate; each random read may need one data CI. |
| Skip-sequential / mixed | Balance BUFND and BUFNI. If the workload switches between sequential and random, buffer pools may be flushed when switching, which can hurt performance. |
In JCL you can pass buffer parameters using the AMP (Access Method Parameters) parameter on the DD statement. The AMP parameter is a comma-separated list of subparameters. For VSAM, BUFND and BUFNI are commonly specified. Example:
123//VSAMDD DD DSN=USERID.FILE.KSDS,DISP=SHR, // AMP=(BUFND=15,BUFNI=5)
Here BUFND=15 allocates 15 data buffers and BUFNI=5 allocates 5 index buffers. The exact values depend on your CI size, CA size, index depth, and workload. For a sequential batch job reading a KSDS, you might use BUFND equal to the number of CIs per CA (or higher) and BUFNI=3. For an online transaction that does random reads by key, you might use a higher BUFNI (e.g. 5–10) and a moderate BUFND (e.g. 5–10). Your installation may have standards or tools to recommend values.
If you omit BUFND and BUFNI, the access method uses system or installation defaults. Defaults are often small (e.g. 2–5 buffers) to conserve memory. For large files or heavy I/O, defaults can cause many more physical I/Os than necessary and slow the job. So for production batch jobs that process VSAM sequentially, or for online applications that do many keyed reads, it is usually worth explicitly setting BUFND and BUFNI based on the file structure and access pattern. Overriding is done per open (per DD or per ACB), so the same cluster can be opened with different buffer counts by different jobs depending on whether they do sequential or random access.
Each buffer uses memory. One data buffer uses CISZ bytes (e.g. 4096 or 8192); one index buffer uses the index CI size (often similar). So BUFND=20 with CISZ=4096 uses 80KB for data buffers; BUFNI=10 with 4KB index CIs uses 40KB for index buffers. Total buffer space is (BUFND × data CISZ) + (BUFNI × index CISZ) for a KSDS. You want enough buffers for good performance but not so many that you exhaust region or storage. On z/OS, region size and other workloads determine how much you can allocate; your shop may have limits or guidelines.
Imagine the buffers as tables in the kitchen. Data buffers are tables where you put full lunchboxes (data CIs); index buffers are a small list on the wall that says which lunchbox is where. If you have lots of tables (many data buffers), you can put many lunchboxes out and grab grapes (records) quickly without going to the pantry (disk) every time. If you have a good list on the wall (enough index buffers), you find the right lunchbox fast. Buffer pool management is deciding how many tables and how big a list to have so that you don't run to the pantry too often.
1. What does BUFND control?
2. For sequential read performance, which buffer count is usually increased?
3. Where can you specify BUFND and BUFNI?