- linkend="pageheaderdata-table">. The first two fields deal with WAL
- related stuff. This is followed by three 2-byte integer fields
+ linkend="pageheaderdata-table">. The first two fields track the most
+ recent WAL entry related to this page. They are followed by three 2-byte
+ integer fields
(pd_lower, pd_upper,
- and pd_special). These represent byte offsets to
- the start
+ and pd_special). These contain byte offsets
+ from the page start to the start
of unallocated space, to the end of unallocated space, and to the start of
the special space.
+ The last 2 bytes of the page header,
+ pd_pagesize_version, store both the page size
+ and a version indicator. Beginning with
+
PostgreSQL 8.0 the version number is 2;
+
PostgreSQL 7.3 and 7.4 used version number 1;
+ prior releases used version number 0.
+ (The basic page layout and header format has not changed in these versions,
+ but the layout of heap row headers has.) The page size
+ is basically only present as a cross-check; there is no support for having
+ more than one page size in an installation.
src/include/storage/bufpage.h.
- Special space is a region at the end of the page that is allocated at page
- initialization time and contains information specific to an access method.
- The last 2 bytes of the page header,
- pd_pagesize_version, store both the page size
- and a version indicator. Beginning with
-
PostgreSQL 7.3 the version number is 1; prior
- releases used version number 0. (The basic page layout and header format
- has not changed, but the layout of heap row headers has.) The page size
- is basically only present as a cross-check; there is no support for having
- more than one page size in an installation.
-
-
Following the page header are item identifiers
(ItemIdData), each requiring four bytes.
An item identifier contains a byte-offset to
- the start of an item, its length in bytes, and a set of attribute bits
+ the start of an item, its length in bytes, and a few attribute bits
which affect its interpretation.
New item identifiers are allocated
as needed from the beginning of the unallocated space.
The final section is the special section
which may
- contain anything the access method wishes to store. Ordinary tables
- do not use this at all (indicated by setting
- pd_special> to equal the pagesize).
+ contain anything the access method wishes to store. For example,
+ b-tree indexes store links to the page's left and right siblings,
+ as well as some other data relevant to the index structure.
+ Ordinary tables do not use a special section at all (indicated by setting
+ pd_special> to equal the page size).
- All table rows are structured the same way. There is a fixed-size
- header (occupying 23 bytes on most machines), followed by an optional null
+ All table rows are structured in the same way. There is a fixed-size
+ header (occupying 27 bytes on most machines), followed by an optional null
bitmap, an optional object ID field, and the user data. The header is
detailed
in . The actual user data
t_cmin
CommandId
4 bytes
- insert CID stamp (overlays with t_xmax)
+ insert CID stamp
|
t_xmax
t_xvac
TransactionId
4 bytes
- XID for VACUUM operation moving row version
+ XID for VACUUM operation moving a row version
|
t_ctid
t_infomask
uint16
2 bytes
- various flags
+ various flag bits
|
t_hoff
Interpreting the actual data can only be done with information obtained
- from other tables, mostly pg_attribute. The
- particular fields are attlen and
- attalign. There is no way to directly get a
+ from other tables, mostly pg_attribute. The
+ key values needed to identify field locations are
+ attlen and attalign.
+ There is no way to directly get a
particular attribute, except when there are only fixed width fields and no
NULLs. All this trickery is wrapped up in the functions
heap_getattr, fastgetattr
whether the field is NULL according to the null bitmap. If it is, go to
the next. Then make sure you have the right alignment. If the field is a
fixed width field, then all the bytes are simply placed. If it's a
- variable length field (attlen == -1) then it's a bit more complicated,
- using the variable length structure varattrib.
- Depending on the flags, the data may be either inline, compressed or in
- another table (TOAST).
+ variable length field (attlen = -1) then it's a bit more complicated.
+ All variable-length datatypes share the common header structure
+ varattrib, which includes the total length of the stored
+ value and some flag bits. Depending on the flags, the data may be either
+ inline or in another table (TOAST); it might be compressed, too.