/*
* Notes on B-Tree tuple format, and key and non-key attributes:
*
* INCLUDE B-Tree indexes have non-key attributes. These are extra
* attributes that may be returned by index-only scans, but do not influence
* the order of items in the index (formally, non-key attributes are not
* considered to be part of the key space). Non-key attributes are only
* present in leaf index tuples whose item pointers actually point to heap
* tuples (non-pivot tuples). _bt_check_natts() enforces the rules
* described here.
*
* Non-pivot tuple format (plain/non-posting variant):
*
* t_tid | t_info | key values | INCLUDE columns, if any
*
* t_tid points to the heap TID, which is a tiebreaker key column as of
* BTREE_VERSION 4.
*
* Non-pivot tuples complement pivot tuples, which only have key columns.
* The sole purpose of pivot tuples is to represent how the key space is
* separated. In general, any B-Tree index that has more than one level
* (i.e. any index that does not just consist of a metapage and a single
* leaf root page) must have some number of pivot tuples, since pivot
* tuples are used for traversing the tree. Suffix truncation can omit
* trailing key columns when a new pivot is formed, which makes minus
* infinity their logical value. Since BTREE_VERSION 4 indexes treat heap
* TID as a trailing key column that ensures that all index tuples are
* physically unique, it is necessary to represent heap TID as a trailing
* key column in pivot tuples, though very often this can be truncated
* away, just like any other key column. (Actually, the heap TID is
* omitted rather than truncated, since its representation is different to
* the non-pivot representation.)
*
* Pivot tuple format:
*
* t_tid | t_info | key values | [heap TID]
*
* We store the number of columns present inside pivot tuples by abusing
* their t_tid offset field, since pivot tuples never need to store a real
* offset (pivot tuples generally store a downlink in t_tid, though). The
* offset field only stores the number of columns/attributes when the
* INDEX_ALT_TID_MASK bit is set, which doesn't count the trailing heap
* TID column sometimes stored in pivot tuples -- that's represented by
* the presence of BT_PIVOT_HEAP_TID_ATTR. The INDEX_ALT_TID_MASK bit in
* t_info is always set on BTREE_VERSION 4 pivot tuples, since
* BTreeTupleIsPivot() must work reliably on heapkeyspace versions.
*
* In version 2 or version 3 (!heapkeyspace) indexes, INDEX_ALT_TID_MASK
* might not be set in pivot tuples. BTreeTupleIsPivot() won't work
* reliably as a result. The number of columns stored is implicitly the
* same as the number of columns in the index, just like any non-pivot
* tuple. (The number of columns stored should not vary, since suffix
* truncation of key columns is unsafe within any !heapkeyspace index.)
*
* The 12 least significant bits from t_tid's offset number are used to
* represent the number of key columns within a pivot tuple. This leaves 4
* status bits (BT_STATUS_OFFSET_MASK bits), which are shared by all tuples
* that have the INDEX_ALT_TID_MASK bit set (set in t_info) to store basic
* tuple metadata. BTreeTupleIsPivot() and BTreeTupleIsPosting() use the
* BT_STATUS_OFFSET_MASK bits.
*
* Sometimes non-pivot tuples also use a representation that repurposes
* t_tid to store metadata rather than a TID. PostgreSQL v13 introduced a
* new non-pivot tuple format to support deduplication: posting list
* tuples. Deduplication merges together multiple equal non-pivot tuples
* into a logically equivalent, space efficient representation. A posting
* list is an array of ItemPointerData elements. Non-pivot tuples are
* merged together to form posting list tuples lazily, at the point where
* we'd otherwise have to split a leaf page.
*
* Posting tuple format (alternative non-pivot tuple representation):
*
* t_tid | t_info | key values | posting list (TID array)
*
* Posting list tuples are recognized as such by having the
* INDEX_ALT_TID_MASK status bit set in t_info and the BT_IS_POSTING status
* bit set in t_tid's offset number. These flags redefine the content of
* the posting tuple's t_tid to store the location of the posting list
* (instead of a block number), as well as the total number of heap TIDs
* present in the tuple (instead of a real offset number).
*
* The 12 least significant bits from t_tid's offset number are used to
* represent the number of heap TIDs present in the tuple, leaving 4 status
* bits (the BT_STATUS_OFFSET_MASK bits). Like any non-pivot tuple, the
* number of columns stored is always implicitly the total number in the
* index (in practice there can never be non-key columns stored, since
* deduplication is not supported with INCLUDE indexes).
*/
引用:
* Pivot tuple format:
*
* t_tid | t_info | key values | [heap TID]
我可以理解非枢轴元组格式。我不明白枢轴元组格式。是同一个非唯一btree key,一个key,多个堆页ctid匹配值吗?