Report: RM Chain & Record Storage
The *.rmchain.rpt files under rpt/ summarize, per table, how the record-management (RM) chain is being used and how the table’s storage parameters compare to its actual record geometry.
They are kicked off byutil/dbanalys.p and written by the rmchainReport procedure insidessg/sausage20.i.
One file is written per database, named <shortname>.rmchain.rpt and placed in $RPTDIR.
What’s in the RM chain?
Progress maintains a per-table RM chain of blocks that have free space
available for new records. A long RM chain isn’t automatically a problem,
but it usually points at one of: a table whose create / toss limits are
out of step with its average row size, a workload that’s churning records
and leaving partly-filled blocks behind, or fragmentation from updates that
grew records past their original block.
Layout
RM Chain Summary for <pt_shortName> <pdbname(1)>
Table Name Size (bytes) Num Recs RM Chain Avg Row RPB xRPB Frag% Ideal Blks RM:Blk Create Toss xToss
-------------------- ----------- ------------ ------------ ------- --- ---- ------- ---------- --------- ------- ------ -----
Rows are restricted to tables with tblist.recs > 0 and sorted bytblist.rm descending so the longest RM chains appear first. Tables whose names start with _ are skipped.
Columns
- Table Name —
tblist.tbl. - Size (bytes) —
tblist.tsz, total data size. - Num Recs —
tblist.recs, current record count. - RM Chain —
tblist.rm, current length of the table’s RM chain (the
headline metric). - Avg Row —
integer( tblist.tsz / tblist.recs ), average bytes per
record. - RPB —
2 ^ _area-recbitsfor the table’s storage area (the configured
records-per-block expressed as the slot count). Shown as?if the area
could not be located. - xRPB —
idealRPB( bsize, avgRecSize ), the suggested RPB given
the average row size and the area’s block size. When xRPB > RPB the
area is leaving slots on the floor; when xRPB < RPB the area is
over-allocating slot pointers for the records it actually stores. - Frag% —
100 * (tblist.frag - tblist.recs) / tblist.recs. Records
larger than a block (or grown past their original block by updates) are
fragmented across multiple blocks; this is the percentage by which the
fragment count exceeds the record count. - Ideal Blks —
ceil( tblist.tsz / bsize ), the minimum number of
blocks the table’s data would occupy if it were perfectly packed. The
comment in the source notes this is “probably a bit too simple-minded” —
it ignores per-block overhead. - RM:Blk —
tblist.rm / idealBlks, the ratio of RM-chain entries to
ideal block count. A value much greater than ~0.1 means a large fraction
of the table’s blocks are sitting on the RM chain rather than holding
records, often a sign that Create / Toss limits are too generous. - Create / Toss —
_storageObject._create-Limitand_storageObject._toss-Limit, the table’s configured create-limit and
toss-limit (default 150 / 300 in s2k_demo). These control when blocks
enter and leave the RM chain. - xToss —
integer( avgRowSize * 1.1 ), a suggested toss limit:
10 % above average row size, i.e. “stop offering this block for new
inserts once it has less free space than ~one row plus a little slack.”
Compare against the configured Toss value.
Alerts
While iterating, two healthcheck alerts are published when zmonName = "healthcheck":
rmChainwhentblist.rm > 1000— RM chain getting unusually long.fragPctwhenFrag% > 1— non-trivial record fragmentation.
These flow through the alarm / alert event channels rather than the
report itself.
Side effects
- After the report is closed,
lib/uploader.pships it off as part of the
ProTop run, same as the other DB-analysis reports.
Reading the report
- High RM Chain and high RM:Blk together = the table has lots
of partly-empty blocks. Tightening the Toss limit (compare against
xToss) prevents the chain from growing further, but the only way
to actually compact or reset a long RM chain is a dump-and-load. - High Frag% = records being split — review whether updates are growing
rows beyond their original block, and whether the Create limit should
be lowered so new records get placed in roomier blocks. - xRPB ≠ RPB = the area’s configured records-per-block is wrong for
this table’s current row size; cross-referencearea.rptto see if the
whole area is mis-tiered. - Large xToss − Toss gap = the toss limit doesn’t match the table’s
current row size; updating it (and bouncing the database) realigns RM
chain behaviour with reality.