Data is stored on disk in files, or extents. Extents are made up of units called blocks. Every block in the DB is the same size (the "DB block size"), but there are different types of blocks for different types of data. Table data goes in RM blocks; index data goes in IX blocks. There are about 20 different types of blocks in the OpenEdge DB, but by quantity most of them are RM and IX blocks.
Each block type has its own internal format. For example, an RM block (in a Type II storage area) is laid out something like this:
- 64-byte block header (contains block address, block backup counter, block type, chain type, address of next block in chain, etc.)
- 4-byte RM header (contains number of used and free directory entries and amount of free space)
- row (or record) directory (contains a two-byte offset for each row stored in the block, pointing to the beginning of that row)
- contiguous free space
- record data
Each record consists of a 2-byte record length, some meta-data about the table and the record (about 14 bytes), and then the field data. The fields are stored in variable-length format so each field consists of a length sub-field (1 or 2 bytes) followed by the field value, a number of bytes specified in the length subfield. These field values are the data you see in your application or queries. Everything else is meta-data.
When you use the RECORD-LENGTH function in ABL, it calculates the size of the entire record, data and meta-data, except for the initial 2-byte record length sub-field. The calculation in dbanalys or tabanalys is similar, except it does include the 2-byte record length in its calculation, so it will be 2 bytes larger than the average you get if you calculate it programmatically. Neither of these calculations includes the record's 2-byte row directory entry. And as you see above, some of the data in a record block has nothing to do with any particular record. This is part of the reason why the total table size shown in dbanalys doesn't match the actual size of a table on disk. Another reason is that there are data structures in the database that describe and help it to manage a table (object blocks, cluster blocks, etc.) but they don't contain record data. These also contribute to the physical size of the table on disk but they are not visible to the ABL.