summaryrefslogtreecommitdiffstats
path: root/doc/src/sgml/html/storage-toast.html
diff options
context:
space:
mode:
Diffstat (limited to 'doc/src/sgml/html/storage-toast.html')
-rw-r--r--doc/src/sgml/html/storage-toast.html225
1 files changed, 225 insertions, 0 deletions
diff --git a/doc/src/sgml/html/storage-toast.html b/doc/src/sgml/html/storage-toast.html
new file mode 100644
index 0000000..9541f89
--- /dev/null
+++ b/doc/src/sgml/html/storage-toast.html
@@ -0,0 +1,225 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>73.2. TOAST</title><link rel="stylesheet" type="text/css" href="stylesheet.css" /><link rev="made" href="pgsql-docs@lists.postgresql.org" /><meta name="generator" content="DocBook XSL Stylesheets Vsnapshot" /><link rel="prev" href="storage-file-layout.html" title="73.1. Database File Layout" /><link rel="next" href="storage-fsm.html" title="73.3. Free Space Map" /></head><body id="docContent" class="container-fluid col-10"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="5" align="center">73.2. TOAST</th></tr><tr><td width="10%" align="left"><a accesskey="p" href="storage-file-layout.html" title="73.1. Database File Layout">Prev</a> </td><td width="10%" align="left"><a accesskey="u" href="storage.html" title="Chapter 73. Database Physical Storage">Up</a></td><th width="60%" align="center">Chapter 73. Database Physical Storage</th><td width="10%" align="right"><a accesskey="h" href="index.html" title="PostgreSQL 15.4 Documentation">Home</a></td><td width="10%" align="right"> <a accesskey="n" href="storage-fsm.html" title="73.3. Free Space Map">Next</a></td></tr></table><hr /></div><div class="sect1" id="STORAGE-TOAST"><div class="titlepage"><div><div><h2 class="title" style="clear: both">73.2. TOAST</h2></div></div></div><div class="toc"><dl class="toc"><dt><span class="sect2"><a href="storage-toast.html#STORAGE-TOAST-ONDISK">73.2.1. Out-of-Line, On-Disk TOAST Storage</a></span></dt><dt><span class="sect2"><a href="storage-toast.html#STORAGE-TOAST-INMEMORY">73.2.2. Out-of-Line, In-Memory TOAST Storage</a></span></dt></dl></div><a id="id-1.10.24.4.2" class="indexterm"></a><a id="id-1.10.24.4.3" class="indexterm"></a><p>
+This section provides an overview of <acronym class="acronym">TOAST</acronym> (The
+Oversized-Attribute Storage Technique).
+</p><p>
+<span class="productname">PostgreSQL</span> uses a fixed page size (commonly
+8 kB), and does not allow tuples to span multiple pages. Therefore, it is
+not possible to store very large field values directly. To overcome
+this limitation, large field values are compressed and/or broken up into
+multiple physical rows. This happens transparently to the user, with only
+small impact on most of the backend code. The technique is affectionately
+known as <acronym class="acronym">TOAST</acronym> (or <span class="quote">“<span class="quote">the best thing since sliced bread</span>”</span>).
+The <acronym class="acronym">TOAST</acronym> infrastructure is also used to improve handling of
+large data values in-memory.
+</p><p>
+Only certain data types support <acronym class="acronym">TOAST</acronym> — there is no need to
+impose the overhead on data types that cannot produce large field values.
+To support <acronym class="acronym">TOAST</acronym>, a data type must have a variable-length
+(<em class="firstterm">varlena</em>) representation, in which, ordinarily, the first
+four-byte word of any stored value contains the total length of the value in
+bytes (including itself). <acronym class="acronym">TOAST</acronym> does not constrain the rest
+of the data type's representation. The special representations collectively
+called <em class="firstterm"><acronym class="acronym">TOAST</acronym>ed values</em> work by modifying or
+reinterpreting this initial length word. Therefore, the C-level functions
+supporting a <acronym class="acronym">TOAST</acronym>-able data type must be careful about how they
+handle potentially <acronym class="acronym">TOAST</acronym>ed input values: an input might not
+actually consist of a four-byte length word and contents until after it's
+been <em class="firstterm">detoasted</em>. (This is normally done by invoking
+<code class="function">PG_DETOAST_DATUM</code> before doing anything with an input value,
+but in some cases more efficient approaches are possible.
+See <a class="xref" href="xtypes.html#XTYPES-TOAST" title="38.13.1. TOAST Considerations">Section 38.13.1</a> for more detail.)
+</p><p>
+<acronym class="acronym">TOAST</acronym> usurps two bits of the varlena length word (the high-order
+bits on big-endian machines, the low-order bits on little-endian machines),
+thereby limiting the logical size of any value of a <acronym class="acronym">TOAST</acronym>-able
+data type to 1 GB (2<sup>30</sup> - 1 bytes). When both bits are zero,
+the value is an ordinary un-<acronym class="acronym">TOAST</acronym>ed value of the data type, and
+the remaining bits of the length word give the total datum size (including
+length word) in bytes. When the highest-order or lowest-order bit is set,
+the value has only a single-byte header instead of the normal four-byte
+header, and the remaining bits of that byte give the total datum size
+(including length byte) in bytes. This alternative supports space-efficient
+storage of values shorter than 127 bytes, while still allowing the data type
+to grow to 1 GB at need. Values with single-byte headers aren't aligned on
+any particular boundary, whereas values with four-byte headers are aligned on
+at least a four-byte boundary; this omission of alignment padding provides
+additional space savings that is significant compared to short values.
+As a special case, if the remaining bits of a single-byte header are all
+zero (which would be impossible for a self-inclusive length), the value is
+a pointer to out-of-line data, with several possible alternatives as
+described below. The type and size of such a <em class="firstterm">TOAST pointer</em>
+are determined by a code stored in the second byte of the datum.
+Lastly, when the highest-order or lowest-order bit is clear but the adjacent
+bit is set, the content of the datum has been compressed and must be
+decompressed before use. In this case the remaining bits of the four-byte
+length word give the total size of the compressed datum, not the
+original data. Note that compression is also possible for out-of-line data
+but the varlena header does not tell whether it has occurred —
+the content of the <acronym class="acronym">TOAST</acronym> pointer tells that, instead.
+</p><p>
+The compression technique used for either in-line or out-of-line compressed
+data can be selected for each column by setting
+the <code class="literal">COMPRESSION</code> column option in <code class="command">CREATE
+TABLE</code> or <code class="command">ALTER TABLE</code>. The default for columns
+with no explicit setting is to consult the
+<a class="xref" href="runtime-config-client.html#GUC-DEFAULT-TOAST-COMPRESSION">default_toast_compression</a> parameter at the time data is
+inserted.
+</p><p>
+As mentioned, there are multiple types of <acronym class="acronym">TOAST</acronym> pointer datums.
+The oldest and most common type is a pointer to out-of-line data stored in
+a <em class="firstterm"><acronym class="acronym">TOAST</acronym> table</em> that is separate from, but
+associated with, the table containing the <acronym class="acronym">TOAST</acronym> pointer datum
+itself. These <em class="firstterm">on-disk</em> pointer datums are created by the
+<acronym class="acronym">TOAST</acronym> management code (in <code class="filename">access/common/toast_internals.c</code>)
+when a tuple to be stored on disk is too large to be stored as-is.
+Further details appear in <a class="xref" href="storage-toast.html#STORAGE-TOAST-ONDISK" title="73.2.1. Out-of-Line, On-Disk TOAST Storage">Section 73.2.1</a>.
+Alternatively, a <acronym class="acronym">TOAST</acronym> pointer datum can contain a pointer to
+out-of-line data that appears elsewhere in memory. Such datums are
+necessarily short-lived, and will never appear on-disk, but they are very
+useful for avoiding copying and redundant processing of large data values.
+Further details appear in <a class="xref" href="storage-toast.html#STORAGE-TOAST-INMEMORY" title="73.2.2. Out-of-Line, In-Memory TOAST Storage">Section 73.2.2</a>.
+</p><div class="sect2" id="STORAGE-TOAST-ONDISK"><div class="titlepage"><div><div><h3 class="title">73.2.1. Out-of-Line, On-Disk TOAST Storage</h3></div></div></div><p>
+If any of the columns of a table are <acronym class="acronym">TOAST</acronym>-able, the table will
+have an associated <acronym class="acronym">TOAST</acronym> table, whose OID is stored in the table's
+<code class="structname">pg_class</code>.<code class="structfield">reltoastrelid</code> entry. On-disk
+<acronym class="acronym">TOAST</acronym>ed values are kept in the <acronym class="acronym">TOAST</acronym> table, as
+described in more detail below.
+</p><p>
+Out-of-line values are divided (after compression if used) into chunks of at
+most <code class="symbol">TOAST_MAX_CHUNK_SIZE</code> bytes (by default this value is chosen
+so that four chunk rows will fit on a page, making it about 2000 bytes).
+Each chunk is stored as a separate row in the <acronym class="acronym">TOAST</acronym> table
+belonging to the owning table. Every
+<acronym class="acronym">TOAST</acronym> table has the columns <code class="structfield">chunk_id</code> (an OID
+identifying the particular <acronym class="acronym">TOAST</acronym>ed value),
+<code class="structfield">chunk_seq</code> (a sequence number for the chunk within its value),
+and <code class="structfield">chunk_data</code> (the actual data of the chunk). A unique index
+on <code class="structfield">chunk_id</code> and <code class="structfield">chunk_seq</code> provides fast
+retrieval of the values. A pointer datum representing an out-of-line on-disk
+<acronym class="acronym">TOAST</acronym>ed value therefore needs to store the OID of the
+<acronym class="acronym">TOAST</acronym> table in which to look and the OID of the specific value
+(its <code class="structfield">chunk_id</code>). For convenience, pointer datums also store the
+logical datum size (original uncompressed data length), physical stored size
+(different if compression was applied), and the compression method used, if
+any. Allowing for the varlena header bytes,
+the total size of an on-disk <acronym class="acronym">TOAST</acronym> pointer datum is therefore 18
+bytes regardless of the actual size of the represented value.
+</p><p>
+The <acronym class="acronym">TOAST</acronym> management code is triggered only
+when a row value to be stored in a table is wider than
+<code class="symbol">TOAST_TUPLE_THRESHOLD</code> bytes (normally 2 kB).
+The <acronym class="acronym">TOAST</acronym> code will compress and/or move
+field values out-of-line until the row value is shorter than
+<code class="symbol">TOAST_TUPLE_TARGET</code> bytes (also normally 2 kB, adjustable)
+or no more gains can be had. During an UPDATE
+operation, values of unchanged fields are normally preserved as-is; so an
+UPDATE of a row with out-of-line values incurs no <acronym class="acronym">TOAST</acronym> costs if
+none of the out-of-line values change.
+</p><p>
+The <acronym class="acronym">TOAST</acronym> management code recognizes four different strategies
+for storing <acronym class="acronym">TOAST</acronym>-able columns on disk:
+
+ </p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
+ <code class="literal">PLAIN</code> prevents either compression or
+ out-of-line storage; furthermore it disables use of single-byte headers
+ for varlena types.
+ This is the only possible strategy for
+ columns of non-<acronym class="acronym">TOAST</acronym>-able data types.
+ </p></li><li class="listitem"><p>
+ <code class="literal">EXTENDED</code> allows both compression and out-of-line
+ storage. This is the default for most <acronym class="acronym">TOAST</acronym>-able data types.
+ Compression will be attempted first, then out-of-line storage if
+ the row is still too big.
+ </p></li><li class="listitem"><p>
+ <code class="literal">EXTERNAL</code> allows out-of-line storage but not
+ compression. Use of <code class="literal">EXTERNAL</code> will
+ make substring operations on wide <code class="type">text</code> and
+ <code class="type">bytea</code> columns faster (at the penalty of increased storage
+ space) because these operations are optimized to fetch only the
+ required parts of the out-of-line value when it is not compressed.
+ </p></li><li class="listitem"><p>
+ <code class="literal">MAIN</code> allows compression but not out-of-line
+ storage. (Actually, out-of-line storage will still be performed
+ for such columns, but only as a last resort when there is no other
+ way to make the row small enough to fit on a page.)
+ </p></li></ul></div><p>
+
+Each <acronym class="acronym">TOAST</acronym>-able data type specifies a default strategy for columns
+of that data type, but the strategy for a given table column can be altered
+with <a class="link" href="sql-altertable.html" title="ALTER TABLE"><code class="command">ALTER TABLE ... SET STORAGE</code></a>.
+</p><p>
+<code class="symbol">TOAST_TUPLE_TARGET</code> can be adjusted for each table using
+<a class="link" href="sql-altertable.html" title="ALTER TABLE"><code class="command">ALTER TABLE ... SET (toast_tuple_target = N)</code></a>
+</p><p>
+This scheme has a number of advantages compared to a more straightforward
+approach such as allowing row values to span pages. Assuming that queries are
+usually qualified by comparisons against relatively small key values, most of
+the work of the executor will be done using the main row entry. The big values
+of <acronym class="acronym">TOAST</acronym>ed attributes will only be pulled out (if selected at all)
+at the time the result set is sent to the client. Thus, the main table is much
+smaller and more of its rows fit in the shared buffer cache than would be the
+case without any out-of-line storage. Sort sets shrink also, and sorts will
+more often be done entirely in memory. A little test showed that a table
+containing typical HTML pages and their URLs was stored in about half of the
+raw data size including the <acronym class="acronym">TOAST</acronym> table, and that the main table
+contained only about 10% of the entire data (the URLs and some small HTML
+pages). There was no run time difference compared to an un-<acronym class="acronym">TOAST</acronym>ed
+comparison table, in which all the HTML pages were cut down to 7 kB to fit.
+</p></div><div class="sect2" id="STORAGE-TOAST-INMEMORY"><div class="titlepage"><div><div><h3 class="title">73.2.2. Out-of-Line, In-Memory TOAST Storage</h3></div></div></div><p>
+<acronym class="acronym">TOAST</acronym> pointers can point to data that is not on disk, but is
+elsewhere in the memory of the current server process. Such pointers
+obviously cannot be long-lived, but they are nonetheless useful. There
+are currently two sub-cases:
+pointers to <em class="firstterm">indirect</em> data and
+pointers to <em class="firstterm">expanded</em> data.
+</p><p>
+Indirect <acronym class="acronym">TOAST</acronym> pointers simply point at a non-indirect varlena
+value stored somewhere in memory. This case was originally created merely
+as a proof of concept, but it is currently used during logical decoding to
+avoid possibly having to create physical tuples exceeding 1 GB (as pulling
+all out-of-line field values into the tuple might do). The case is of
+limited use since the creator of the pointer datum is entirely responsible
+that the referenced data survives for as long as the pointer could exist,
+and there is no infrastructure to help with this.
+</p><p>
+Expanded <acronym class="acronym">TOAST</acronym> pointers are useful for complex data types
+whose on-disk representation is not especially suited for computational
+purposes. As an example, the standard varlena representation of a
+<span class="productname">PostgreSQL</span> array includes dimensionality information, a
+nulls bitmap if there are any null elements, then the values of all the
+elements in order. When the element type itself is variable-length, the
+only way to find the <em class="replaceable"><code>N</code></em>'th element is to scan through all the
+preceding elements. This representation is appropriate for on-disk storage
+because of its compactness, but for computations with the array it's much
+nicer to have an <span class="quote">“<span class="quote">expanded</span>”</span> or <span class="quote">“<span class="quote">deconstructed</span>”</span>
+representation in which all the element starting locations have been
+identified. The <acronym class="acronym">TOAST</acronym> pointer mechanism supports this need by
+allowing a pass-by-reference Datum to point to either a standard varlena
+value (the on-disk representation) or a <acronym class="acronym">TOAST</acronym> pointer that
+points to an expanded representation somewhere in memory. The details of
+this expanded representation are up to the data type, though it must have
+a standard header and meet the other API requirements given
+in <code class="filename">src/include/utils/expandeddatum.h</code>. C-level functions
+working with the data type can choose to handle either representation.
+Functions that do not know about the expanded representation, but simply
+apply <code class="function">PG_DETOAST_DATUM</code> to their inputs, will automatically
+receive the traditional varlena representation; so support for an expanded
+representation can be introduced incrementally, one function at a time.
+</p><p>
+<acronym class="acronym">TOAST</acronym> pointers to expanded values are further broken down
+into <em class="firstterm">read-write</em> and <em class="firstterm">read-only</em> pointers.
+The pointed-to representation is the same either way, but a function that
+receives a read-write pointer is allowed to modify the referenced value
+in-place, whereas one that receives a read-only pointer must not; it must
+first create a copy if it wants to make a modified version of the value.
+This distinction and some associated conventions make it possible to avoid
+unnecessary copying of expanded values during query execution.
+</p><p>
+For all types of in-memory <acronym class="acronym">TOAST</acronym> pointer, the <acronym class="acronym">TOAST</acronym>
+management code ensures that no such pointer datum can accidentally get
+stored on disk. In-memory <acronym class="acronym">TOAST</acronym> pointers are automatically
+expanded to normal in-line varlena values before storage — and then
+possibly converted to on-disk <acronym class="acronym">TOAST</acronym> pointers, if the containing
+tuple would otherwise be too big.
+</p></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="storage-file-layout.html" title="73.1. Database File Layout">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="storage.html" title="Chapter 73. Database Physical Storage">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="storage-fsm.html" title="73.3. Free Space Map">Next</a></td></tr><tr><td width="40%" align="left" valign="top">73.1. Database File Layout </td><td width="20%" align="center"><a accesskey="h" href="index.html" title="PostgreSQL 15.4 Documentation">Home</a></td><td width="40%" align="right" valign="top"> 73.3. Free Space Map</td></tr></table></div></body></html> \ No newline at end of file