Reading the Data Component of a KSDS separately as an ESDS is simple in Assembler using MACRF=ADR on the ACB and OPTCD=(ADR,RBA) on the RPL. I have a vague memory of also doing this with COBOL (I remember seeing it recommended somewhere for efficiency) but all my attempts in the last 3 days have failed. Now I wonder if I ever actually *did* do this in COBOL.
VSAM.FILE <- Cluster
VSAM.FILE.DATA <- Data (THIS is what I want to read directly, eg with "//ESDS DD DISP=SHR,DSN=VSAM.FILE.DATA" in JCL)
VSAM.FILE.INDEX <- Index
Has anyone here ever done this in COBOL? For sequential processing of a KSDS, it's supposed to eliminate the needless overhead of having to go through the Index.
Here are my "best effort" SELECT and FD, which work fine for reading an ESDS defined as such, but does NOT work for reading the Data component of a KSDS directly:
SELECT INFILE ASSIGN AS-INFILE
01 INREC PIC X(80).
For testing, I defined KSDS and ESDS files with AVG and MAX LRECL both = 80. KSDS has "KEYS (8 0)" but I don't think that matters. Both files have 8 identical records with an 8-digit sequence number in columns 1 through 8.
With Assembler, I can read both the ESDS and the KSDS Data Component using one program coded to read an ESDS sequentially. But with COBOL, I can only read the file defined as an ESDS. When I try to read the KSDS Data component as an ESDS, I get File Status 39: "The OPEN statement was unsuccessful because a conflict was detected between the fixed file attributes and the attributes specified for that file in the program....".
If anyone here knows how to code a COBOL program to read a KSDS data component as an ESDS, I'd LOVE to know how you do it!
FWIW, it's easy in Assembler. The following 20 lines of code will read and display all records from a fixed-length ESDS defined as such OR a the data component of a KSDS. To Assembler, they appear identical.
LOOP GET RPL=RPL
L 0,REC@ R0 -> ESDS RECORD
PUT DCB,(0) OUTPUT
B LOOP CONTINUE
EOF CLOSE (ACB,,DCB)
BR 14 RETURN
DCB DCB DDNAME=OUTFILE,DSORG=PS,MACRF=PM
ACB ACB DDNAME=INFILE,MACRF=ADR,EXLST=EXLST
RPL RPL ACB=ACB,ARG=XRBA,AREA=REC@,OPTCD=(ADR,LOC,XRBA)
EXLST EXLST EODAD=EOF
R14SAVE DS F
XRBA DS XL8
REC@ DS A
JCL to run the above:
// EXEC PGM=READESDS
//OUTFILE DD SYSOUT=*,DCB=(RECFM=FB,LRECL=<lrecl>)
//INFILE DD DISP=SHR,DSN=<ESDS or KSDS Data Compenent>
Joined: 06 Jun 2008 Posts: 8547 Location: Dubuque, Iowa, USA
What does your assembler code do in the case of CA splits on the KSDS data set? The records will not be physically stored in entry sequence, nor will they be physically stored in key sequence after a CA split.
I think what you've done is write an assembler program to return KSDS records in a semi-random fashion.
The records will be returned in whatever order they are in on the data component. If sequence doesn't matter, and sometimes it doesn't, then reading from the data component directly saves the overhead of going through the index.
I'll try to find where I saw this recommended. I think it may have been in one of the Jay Ranade books.
Joined: 23 Nov 2006 Posts: 19254 Location: Inside the Matrix
I'll not go into pro's and con's, but I believe the data should be read in the way intended. What happens if some internal improvement is made to the access method and "old" tricky code "falls down" after an upgrade.
From my own experience, exponentially more can be done in assembler but it should rarely (if ever) be used for business application code. Each year there are fewer and fewer people who Actually Know assembler. Getting a couple of routines to run does Not constitute knowing assembler. Besides, most organizations will not allow new assembler application code to be built/promoted.
But I thought the question was doing something like this using COBOL. COBOL does not do what you want, so i'd suggest using COBOL as it is intended. Someone else will have to maintain this when you have moved on. . .
This is a quest for knowledge, not a business solution, so I'm not concerned with maintenance issues or acceptability. The question is indeed "How can this be done in COBOL?" So far, I've just heard "I know of no way". For me, that's not a good enough reason to give up.
It is a quest spurred on by a smarmy salesman and the question of why it can be done in Assembler and not in COBOL. It is just extending a Proof of Concept.
It comes down to "can a KSDS data component be read directly in COBOL without going through the index levels (with the consequences which flow from that)?"
If there are any "yes, this way" or "perhaps, try this" or "definitely not, becuase of this" on the technical issues, that would be good.
It is not destined for Production, as there are more shortcomings in addition to those alfready pointed out.
Results so far suggest that up to 50% of the processing of a KSDS serially (in key sequence) is due to the indexes. There will be no solid figure for this, as it depends on so many things, We all unloading a KSDS to a PS and processing it sequentially then reloading it doesn't require many steps using the PS to give performance benefits. We know why. Is there a way to do it differently, in limited circumstances (order of the data not relevant to the program)?
Specifically relating to the question that is, not just a further pile of suggestions on how to do it differently :-)
(2) Using SORT FIELDS=COPY from KSDS Data to an ESDS, SORT says "ICE076A 0 VSAM INPUT ERROR L(72) SORTIN", which translates to "The application made a keyed request for access to an entry-sequenced data set." Interesting that it recognizes the input as an ESDS, but then tries to do a keyed read.
PRINT and REPRO are designed to work with everything they are documented for.
DFSORT is not doing a keyed read. It is making some access which implies a KSDS. DFSORT does not do keyed reads as such, but of course would, for a KSDS, inform AMS that it wanted to process the dataset for serial input.
> "I'll try to find where I saw this recommended.
> I think it may have been in one of the Jay Ranade books."
Definitely not the 1987 edition of "VSAM: Performance, Design, and Fine Tuning." Ordered a 1986 edition of his "VSAM, Concepts, Programming and Design" - will see if it's in there.
Now I wonder if it was in one of Xephon's monthly "MVS" or "VSAM" "Update" booklets.
In the COBOL group on LinkedIn, James McGee of Aflac suggested: "Create an Alternate index that references RBA..." Using an Alternate Index requires special setup and entails a lot of extra overhead, but for the purpose of using COBOL to read exactly the same records in either key sequence or entry sequence, it at least does work.
The following JCL creates an fixed-length ESDS base cluster, loads it with 80-byte records with an 8-byte "key" in pos 1, then builds an alternate index based on that "key" with records pointing to the corresponding RBAs in the ESDS:
// EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
DEFINE CLUSTER (NAME(VSAM.ESDS) RECSZ (80 80) TRK (1) -
REPRO INFILE (INFILE) OUTDATASET (VSAM.ESDS)
DEFINE AIX (NAME (VSAM.RBAKEYS) RELATE (VSAM.ESDS) KEYS (8 0) -
RECSZ (17 17) TRK (1) UNIQUEKEY UPGRADE)
BLDINDEX INDATASET (VSAM.ESDS) OUTDATASET (VSAM.RBAKEYS)
DEFINE PATH (NAME (VSAM.KSDS) PATHENTRY (VSAM.RBAKEYS))
//INFILE DD *
00000100 THIS IS THE FIRST RECORD
00000200 THIS IS THE SECOND RECORD
00000300 THIS IS THE THIRD RECORD
OPEN INPUT ESDS SET NOT-EOF TO TRUE
PERFORM UNTIL EOF READ ESDS
AT END SET EOF TO TRUE CLOSE ESDS
NOT AT END DISPLAY ESDS-RECORD END-READ END-PERFORM
OPEN INPUT KSDS SET NOT-EOF TO TRUE
PERFORM UNTIL EOF READ KSDS
AT END SET EOF TO TRUE CLOSE KSDS
NOT AT END DISPLAY KSDS-RECORD END-READ END-PERFORM
And the JCL to run the sample:
// EXEC PGM=SAMPLE
//SYSOUT DD SYSOUT=*
//ESDS DD DISP=SHR,DSN=VSAM.ESDS <- Base Cluster
//KSDS DD DISP=SHR,DSN=VSAM.KSDS <- Path (to the RBAKEYS Alt Index)
http://www.jaymoseley.com/hercules/vstutor/vstutor.htm - Not having much experience with Alternate Indices, I found the section of Jay Moseley's VSAM Tutorial on the subject (near the bottom) to be very helpful. The trickiest part for me was understanding the Record Size for the Alternate Index. With unique keys (as in this example) the AIX records are fixed length. The record size of 17 (for this example) was then calculated as follows (a+b+c):
(a) 5 bytes for control information
(b) Key length (8 bytes in this case)
(c) RBA length (4 bytes)
> I'll try to find where I saw this recommended.
> I think it may have been in one of the Jay Ranade books.
It may indeed have been Jay Ranade's "VSAM Concepts, Programming and Design" (1985 - ISBN 0-07-051198-5). While it doesn't specifically mention sequential processing and does specify use of assembler, it is basically the same idea. From pages 21 & 23: "By programming an access routine in assembler language, you can access a record randomly in a KSDS or an ESDS if you know the RBA of the record. In such a case, you will bypass the index component of the KSDS and the access will be faster... Records in KSDS's and ESDS's can be accesed through an RBA. This is quicker than keyed access because it does not involve an index search."