# 1.1 The Physical Suitcase (The Tuple)

In the depot of the Lazy Elephant, a **Tuple** is the absolute smallest unit
of luggage. It’s not just a "row" of data; it’s a highly specific, slightly
neurotic physical suitcase that carries everything a record needs to survive its
journey through the database.
It is critical to distinguish between the **Logical Row** and the **Physical
Tuple**:
- **The Row (Logical)**: This is the "ghost" or the "idea" of a record. When you
say `SELECT * FROM animals WHERE id=1`, you are asking for the _concept_ of that
animal.
- **The Tuple (Physical)**: This is the actual physical suitcase sitting on a
conveyor belt. Because of the elephant's refusal to erase things (see
[[Chapter 1/1.4 - The Sharpie Ledger (MVCC)|1.4 - The Art of the Sharpie]]), a single logical **Row** might actually be
represented by dozens of physical **Tuples**—old versions, newer versions, and
deleted versions.
---
## 1. The Header (`HeapTupleHeaderData`)
Living in the front pocket of every suitcase is a slightly stressed **Bureaucratic Bird** (the Header). Under the hood, this is literally the C-struct `HeapTupleHeaderData` defined in the Postgres engine. This 23-byte fixed-size structure is the "passport" of the tuple. It tells the system who created it, who deleted it, and whether it’s even legal to look at it without a formal invitation to a tea party.
| Field | Size | Metaphor | Technical Description |
| :----------- | :------ | :------------------- | :-------------------------------------------------------------------- |
| `t_xmin` | 4 bytes | **Creation Stamp** | The Transaction ID (XID) that inserted this tuple. |
| `t_xmax` | 4 bytes | **Deletion Stamp** | The Transaction ID that deleted or locked this tuple. |
| `t_cid` | 4 bytes | **Command ID** | The specific command within the transaction that acted on it. |
| `t_ctid` | 6 bytes | **Location Tag** | The physical address (Page #, Offset) of this tuple or its successor. |
| `t_infomask` | 2 bytes | **Visibility Flags** | Bitflags describing the tuple's state (commits, aborts, has nulls). |
> [!NOTE]
> The `t_ctid` is the physical "GPS coordinate" of the suitcase defined as `(blockNumber, offsetNumber)`. If a row is updated, the old tuple’s `t_ctid` is updated to point to the new physical location of the next version. It’s like a trail of breadcrumbs, but the birds are too busy with paperwork to eat them!
### The Ghost Items (System Columns)
Because of the Bird's meticulous record-keeping, every single tuple you create is secretly carrying extra "ghost" items you never asked for. Even if your table only has one column `(name text)`, the elephant quietly packs several **System Columns** into the suitcase.
If you ever want to see these hidden passengers, you can explicitly ask the elephant for them in your query. Let's look at a specific animal in our cafe:
```sql
-- Asking for the hidden passengers
SELECT ctid, xmin, xmax, name
FROM animals
WHERE name = 'Babu';
```
The elephant will return something like this:
| ctid | xmin | xmax | name |
| :---- | :--- | :--- | :--- |
| (0,1) | 501 | 0 | Babu |
* **`ctid (0,1)`**: This is the literal physical address in the depot: **Page 0, Offset 1**.
* **`xmin 501`**: This is the ID of the transaction that "packed" this suitcase (inserted the row).
* **`xmax 0`**: Since this is 0, it means nobody has "marked" this suitcase for deletion yet. It is a live, happy row!
It’s a glimpse into the matrix!
## 2. The Null Bitmap (The Checklist)
If your table has many columns that might be empty (NULL), the elephant doesn't want to waste suitcase space on them. Instead, it maintains a **Checklist** (the Null Bitmap) right after the header.
If a bit is set to 0, the elephant knows that specific "item" wasn't packed, and it skips over it entirely when unpacking the suitcase. How very efficient!
## 3. The Padding Socks (Alignment)
Postgres prefers to pick up suitcases in 8-byte chunks. If your data (Header + Bitmap + User Data) doesn't end on an 8-byte boundary, the elephant stuffs **Useless Padding Socks** into the corners.
This is why a table with `(int, char(1), int)` might actually take up more space than `(int, int, char(1))`. The order of your belongings matters! It’s enough to make one’s hat spin!
## 4. TOAST (Oversized Attribute Storage)
How curious! What if a single item is too big for the suitcase (usually > 2KB)?
The elephant won't struggle with it. He won't push it, pull it, or try to fold it like a waistcoat. Instead, he ships the large item off to a **Separate Trailer** (the TOAST table) and leaves a tiny "Claim Check" in the suitcase.
TOAST stands for **The Oversized-Attribute Storage Technique**, and it is the reason you can store multi-gigabyte "life story" strings without breaking the 8KB [[Structures/Page|Page]] limit.
---
[[Chapter 1/1.0 - The Building Blocks of Storage|← 1.0 - The Logical vs. The Physical]] | [[Chapter 1/1.0 - The Building Blocks of Storage|↑ 1.0 - The Logical vs. The Physical]] | [[Chapter 1/1.2 - The Shipping Container (The Page)|1.2 - The Standard Size (8KB) →]]