SPLITBY is an OUTFIL parameter that splits the output stream into multiple datasets by record count. You specify SPLITBY=n and one or more output DD names (in FNAMES=). How the records are distributed depends on how you code the OUTFIL(s). With a single OUTFIL and FNAMES=(OUT1,OUT2,OUT3) and SPLITBY=500, the first 500 records go to OUT1, the next 500 to OUT2, the next 500 to OUT3, then the next 500 go to OUT1 again—so blocks rotate across the files. With two OUTFILs—first FNAMES=OUT1,SPLITBY=500 and second FNAMES=OUT2—the first 500 records go to OUT1 and all remaining records go to OUT2. So SPLITBY lets you break one large output into fixed-size chunks, either rotating across several files or sending the first chunk to one file and the rest to another. Related options include SPLIT=n (often with multiple OUTFILs) and SPLIT1R=n (contiguous chunks, remainder to last file). This page covers SPLITBY syntax, the two-OUTFIL pattern (first n / remainder), rotating blocks with multiple FNAMES, and how SPLITBY compares to SPLIT and SPLIT1R.
Pattern 1 — First n to one file, remainder to another: Use two OUTFIL statements. The first has FNAMES=OUT1 and SPLITBY=n; the second has FNAMES=OUT2 only (no SPLITBY). The first n records go to OUT1; every record after that goes to OUT2. This is useful when you want a fixed-size "first chunk" (e.g. for a control file or sample) and the rest in a second file.
12OUTFIL FNAMES=OUT1,SPLITBY=500 OUTFIL FNAMES=OUT2
Pattern 2 — Rotating blocks across multiple files: Use one OUTFIL with FNAMES=(OUT1,OUT2,OUT3,...) and SPLITBY=n. Records are sent in blocks of n to OUT1, then OUT2, then OUT3, then back to OUT1, and so on. So each file receives every k-th block (where k is the number of DDs). With three files and SPLITBY=500, OUT1 gets records 1–500, 1501–2000, 3001–3500, ...; OUT2 gets 501–1000, 2001–2500, ...; OUT3 gets 1001–1500, 2501–3000, .... The files end up with roughly equal counts when the total record count is large.
1OUTFIL FNAMES=(OUT1,OUT2,OUT3),SPLITBY=500
| Variant | Behavior | Typical use |
|---|---|---|
| SPLITBY=n, FNAMES=(A,B,C) | First n to A, next n to B, next n to C, then next n to A (cycle) | Rotating blocks across 3+ files |
| SPLITBY=n, two OUTFILs (OUT1 then OUT2) | First n to OUT1, all remaining to OUT2 | First chunk to one file, remainder to second |
| SPLIT=n, multiple OUTFILs | First n to first OUTFIL, next n to second OUTFIL | Sequential chunks to different files |
| SPLIT1R=n | Contiguous chunks of n per file; remainder to last | Roughly equal-sized files, no rotation |
The value n in SPLITBY=n is the number of records per block. Choose n based on your requirement: for example, 10,000 if a downstream system accepts at most 10,000 records per file; or 1,000 for a sample. With rotating blocks (multiple FNAMES), larger n means fewer "switches" between files but larger chunks; smaller n means more even distribution as records are written. The total number of records is not required to be a multiple of n—the last block may be partial, and (depending on product) it may go to the next file in rotation or to the last file.
SPLIT=n is often used with multiple OUTFILs: one OUTFIL per output file, each with FNAMES= one DD and SPLIT=n. Then the first n records go to the first OUTFIL's file, the next n to the second, and so on. So you get sequential chunks: file1 has records 1–n, file2 has n+1–2n, etc., without cycling. SPLITBY=n with a single OUTFIL and a list of FNAMES gives the rotating behavior described above. Some products use the two keywords interchangeably or with slightly different semantics; always check your DFSORT manual for the exact behavior on your system.
SPLIT1R=n (or SPLIT 1R) typically means: fill the first output with n records, then the second with n records, then the third with n, and so on. After filling each file once (or in order), any remainder usually goes to the last output dataset. So you do not get rotation—you get contiguous segments. For example, with 2500 records, n=1000, and two files: first file gets 1000, second gets 1500 (remainder). With three files, first gets 1000, second gets 1000, third gets 500. Syntax and exact behavior are product-dependent; see your manual.
Each DD name in FNAMES= must have a corresponding DD statement in JCL. The record length written is the same for all split files—either the full record length (after INREC/OUTREC if used) or the length defined by BUILD= on that OUTFIL. So set LRECL (and RECFM) on each DD to match. SPACE and DISP should be appropriate for the expected number of records per file (e.g. if you expect ~10,000 records per file, allocate enough space).
You can combine SPLITBY with BUILD= (or other OUTFIL options). The record is reformatted according to BUILD= first, and then the built record is distributed by SPLITBY to the appropriate output. So all split files receive the same record format; only the count per file differs.
You have a long line of cards and three boxes. SPLITBY=500 means: put the first 500 cards in box 1, the next 500 in box 2, the next 500 in box 3, then the next 500 in box 1 again, then box 2, then box 3, and so on. So the boxes take turns getting 500 cards each. That way no single box gets the whole pile—they share in blocks. SPLITBY is the rule that says "every 500 cards, switch to the next box (and after the last box, start from the first)."
1. What does SPLITBY=n do with FNAMES=(OUT1,OUT2,OUT3)?
2. If you use two OUTFILs—first FNAMES=OUT1,SPLITBY=500 and second FNAMES=OUT2—where do the first 500 records go? Where do the rest go?
3. What is the difference between SPLIT and SPLITBY?
4. What is SPLIT1R used for?
5. Why would you use SPLITBY with multiple FNAMES instead of multiple OUTFILs with SPLIT?