A logical I/O transfers one (or more) records between the program work area and the database management file buffer. One may say that a logical I/O basically boils down to a move internally in main memory; but although logical I/Os are done entirely by the CPU and thus are rather fast, it involves quite some overhead, possibly even including use of an index to locate a record to be read. A job having many logical I/Os will thus inevitably always use much CPU time.
A logical I/O is caused by a read or write (or update, delete, ...) instruction in the program. Such I/Os are never carried out by the program itself – the compiler generates a call to the appropriate operating system I/O routine. A logical I/O may also transfer a block of records – this may be requested by the program automatically or through use of the SEQONLY keyword of the OVRDBF command – in which case several records are transferred between the program buffer and data management per logical I/O.
Logical I/Os may or may not trigger one or more physical I/Os (= access to the disk). If a file is being read sequentially in “arrival sequence”, i.e. in the sequence in which the records are stored on the disk, the next record is likely to be within the same page or block of data; or database management may have read the next record ahead of time, or the record may happen to be in main storage because it was used recently by the same or even by another job.
Therefore, if the next record wanted by the program already has been fetched into main memory, a physical I/O is not needed for carrying out the I/O request.
But one logical I/O could also trigger several physical I/Os, the worst case probably being the random reading of a joined logical file. When the program wants to read one join file record by key, both the indexes and the data spaces of the physical files behind the join file must be accessed, probably all synchronously. This could result in a noticeable wait for the program.