From 6510d5253ec0a0c4c46341784b411f64f12e2e07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Herrera?= Date: Wed, 7 Oct 2026 14:24:37 +0200 Subject: [PATCH] Revamp REPACK doc refentry page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The page a bit of a mess, with notes interpersed in the list of parameters, and two "notes" subsections that weren't in the Notes section. Limit the commentary under "Description" and "Parameters" to a minimum; move the existing text to appear in the "Notes" section. Both the "Notes on Clustering" and "Notes on Resources" subsections, which were under "Description", are moved to be under "Notes" instead. Add a new "Notes on Concurrent Operation" subsection there, which now carries some text that was in "Parameters", and gets some additional text to (hopefully) explain resource consumption more clearly -- notably, the hard limit of 104 million tuples that can be concurrently updated/deleted before running into the palloc size limit. Add appropriate cross-links. Author: Radim Marek Author: Álvaro Herrera Author: Shihao Zhong Backpatch-through: 19 Discussion: https://postgr.es/m/CAJgoLk+dodrwuwCuXERGYwgjQzSwrKd+xgitYrL32oWDt39zvA@mail.gmail.com --- doc/src/sgml/ref/repack.sgml | 507 +++++++++++++++++++---------------- 1 file changed, 271 insertions(+), 236 deletions(-) diff --git a/doc/src/sgml/ref/repack.sgml b/doc/src/sgml/ref/repack.sgml index 346cba89c90..14651715013 100644 --- a/doc/src/sgml/ref/repack.sgml +++ b/doc/src/sgml/ref/repack.sgml @@ -61,16 +61,149 @@ REPACK [ ( option [, ...] ) ] USING If a USING INDEX clause is specified, the rows are - physically reordered based on information from an index. Please see the - notes on clustering below. + physically reordered based on information from an index. Please see + below. When a table is being repacked, an ACCESS EXCLUSIVE lock - is acquired on it. This prevents any other database operations (both reads - and writes) from operating on the table until the REPACK - is finished. If you want to keep the table accessible during the repacking, - consider using the CONCURRENTLY option. + is acquired on it, unless the CONCURRENTLY option is given. + See for a discussion + on the effects of this option. + + + + + Parameters + + + + table_name + + + The name (possibly schema-qualified) of a table. + + + + + + column_name + + + The name of a specific column to analyze. Defaults to all columns. + If a column list is specific, ANALYZE must also + be specified. + + + + + + index_name + + + The name of an index. + + + + + + CONCURRENTLY + + + Allow other transactions to use the table while it is being repacked. + See for more details. + + + + + + + VERBOSE + + + Prints a progress report as each table is repacked + at INFO level. + + + + + + ANALYZE + ANALYSE + + + Applies on the table after repacking. This is + currently only supported when a single (non-partitioned) table is specified. + This option cannot be used inside a transaction block, or from a function, + procedure, or DO block. + + + + + + boolean + + + Specifies whether the selected option should be turned on or off. + You can write TRUE, ON, or + 1 to enable the option, and FALSE, + OFF, or 0 to disable it. The + boolean value can also + be omitted, in which case TRUE is assumed. + + + + + + + + Notes + + + To repack a table, one must have the MAINTAIN privilege + on the table. + + + + REPACK is primarily meant to remove bloat and, with + USING INDEX, to cluster the table, in order to improve + performance. Although it also advances the table's + relfrozenxid and relminmxid, + it is not a good way to prevent transaction ID or multixact ID wraparound: + it rewrites the whole table and all of its indexes, so it takes much longer + than VACUUM, and it can fail after most of the work + is done, especially with CONCURRENTLY on a busy table. + VACUUM is recommended for that instead (see + ). + When a table gets close to wraparound, VACUUM skips index + vacuuming on its own (see ), and its + INDEX_CLEANUP OFF + option can do the same earlier. + + + + REPACK refuses to process a table on which an invalid + index exists. Such indexes must be dropped or reindexed by the user ahead + of time. + + + + While REPACK is running, the is temporarily changed to pg_catalog, + pg_temp. + + + + Each backend running REPACK will report its progress + in the pg_stat_progress_repack view. See + for details. + + + + Repacking a partitioned table repacks each of its partitions. If an index + is specified, each partition is repacked using the partition of that + index. REPACK on a partitioned table cannot be executed + inside a transaction block. @@ -141,27 +274,37 @@ REPACK [ ( option [, ...] ) ] USING all tables which have a clustering index defined and which the calling user has privileges for are processed. - Notes on Resources - When an index scan or a sequential scan without sort is used, a temporary - copy of the table is created that contains the table data in the index - order. Temporary copies of each index on the table are created as well. - Therefore, you need free space on disk at least equal to the sum of the - table size and the index sizes. + REPACK creates a temporary copy of the table and all + of its indexes, so you need free disk space at least equal to the sum + of the table size and the index sizes. - When a sequential scan and sort is used, a temporary sort file is also - created, so that the peak temporary space requirement is as much as double - the table size, plus the index sizes. This method is often faster than - the index scan method, but if the disk space requirement is intolerable, - you can disable this choice by temporarily setting - to off. + If the USING INDEX clause is given and the planner + chooses a sequential scan and sort to implement it, a temporary sort + file of up to the size of the table is needed in addition to the above. + This method is usually faster than an index scan, but if the disk space + requirement is intolerable, you can disable this choice by temporarily + setting to off; or + omitting USING INDEX if the table doesn't need to be + reordered. + + + + For the purposes of transaction ID wraparound + (see ), + REPACK is considered a single long-running + transaction, which prevents VACUUM from cleaning + up dead rows from other tables. + It is advisable to monitor pg_stat_activity.backend_xid + for the process running REPACK when repacking + very large tables, to avoid causing excessive bloat in other tables. @@ -171,244 +314,136 @@ REPACK [ ( option [, ...] ) ] USING - + + Notes on Concurrent Operation - - Parameters + + + REPACK with the CONCURRENTLY + option is not MVCC-safe. After the repacking transaction commits, + the table will appear empty to concurrent transactions, if they are + using a snapshot taken before repacking started. + See for more details. + + - - - table_name - - - The name (possibly schema-qualified) of a table. - - - + + REPACK copies the contents of the table + (ignoring dead tuples) into a new file, sorted by the specified index, + and also creates a new file for each index. It then swaps the old and + new files for the table and all the indexes, and deletes the old files. + Without the CONCURRENTLY option, an + ACCESS EXCLUSIVE lock is acquired at the beginning + and remains held throughout the operation to make sure that the old + files do not change during the processing; otherwise, any concurrent + changes would get lost due to the swap. + - - column_name - - - The name of a specific column to analyze. Defaults to all columns. - If a column list is specific, ANALYZE must also - be specified. - - - + + By contrast, when the CONCURRENTLY option is + specified, the bulk of the operation is run with + SHARE UPDATE EXCLUSIVE lock, and the + ACCESS EXCLUSIVE lock is only acquired + during the final phase to swap the table and index files. + The data changes that took place during the creation of the new + table and index files are captured using logical decoding + (see ) and applied before + the ACCESS EXCLUSIVE lock is requested. + Once that lock is obtained, a final pass over any remaining captured + concurrent data changes is done and the files are swapped. + Thus the lock is typically held for a short time, depending + on the amount of changes accumulated while the lock was being + waited for. + - - index_name - - - The name of an index. - - - + + Processing of these concurrent changes requires a fixed small + amount of memory for each tuple concurrently updated or deleted, + not limited by ; + if more than about 104 million rows are concurrently updated or + deleted during the execution of REPACK, the + command fails. In addition, the complete tuple data for all + concurrent changes (except for TOAST columns that are not modified + by UPDATE) are stored on disk separately. + - - CONCURRENTLY - - - Allow other transactions to use the table while it is being repacked. - + + REPACK (CONCURRENTLY) might fail to complete if DDL + commands are executed on the table by other transactions during the + repacking. + - - Internally, REPACK copies the contents of the table - (ignoring dead tuples) into a new file, sorted by the specified index, - and also creates a new file for each index. Then it swaps the old and - new files for the table and all the indexes, and deletes the old - files. The ACCESS EXCLUSIVE lock is needed to make - sure that the old files do not change during the processing because the - changes would get lost due to the swap. - + + REPACK (CONCURRENTLY) USING INDEX + does not try to order the rows inserted into the table after the + repacking started. + - - With the CONCURRENTLY option, the ACCESS - EXCLUSIVE lock is only acquired to swap the table and index - files. The data changes that took place during the creation of the new - table and index files are captured using logical decoding - () and applied before - the ACCESS EXCLUSIVE lock is requested. Thus the lock - is typically held only for the time needed to swap the files, which - should be pretty short. However, the time might still be noticeable if - too many data changes have been done to the table while - REPACK was waiting for the lock: those changes must - be processed just before the files are swapped, while the - ACCESS EXCLUSIVE lock is being held. - + + The CONCURRENTLY option cannot be used in the + following cases: - - Note that REPACK with the - CONCURRENTLY option does not try to order the rows - inserted into the table after the repacking started. Also - note REPACK might fail to complete due to DDL - commands executed on the table by other transactions during the - repacking. - - - + + - In addition to the temporary space requirements explained in - , - the CONCURRENTLY option can add to the usage of - temporary space a bit more. The reason is that other transactions can - perform DML operations which cannot be applied to the new file until - REPACK has copied all the existing tuples from the - old file. Thus the tuples inserted into the old file during the copying - are also stored separately in a temporary file, until they can be - processed. + The relation is not a table (e.g., it is a materialized view). - + - - The CONCURRENTLY option cannot be used in the - following cases: - - - - - The relation is not a table (e.g., it is a materialized view). - - - - - - The table is UNLOGGED. - - - - - - The table is partitioned. - - - - - - The table lacks a primary key and index-based replica identity. - - - - - - The table is a system catalog or a TOAST table. - - - - - - The table's access method is not heap. - - - - - - The table is declared as a catalog table using the - user_catalog_table - storage parameter. - - - - - - REPACK is executed inside a transaction block. - - - - - - The max_repack_replication_slots - configuration parameter does not allow for the creation of an - additional replication slot. - - - - - - + - REPACK with the CONCURRENTLY - option is not MVCC-safe, see for - details. + The table is UNLOGGED. - + - - + + + The table is partitioned. + + - - VERBOSE - - - Prints a progress report as each table is repacked - at INFO level. - - - + + + The table lacks a primary key and index-based replica identity. + + - - ANALYZE - ANALYSE - - - Applies on the table after repacking. This is - currently only supported when a single (non-partitioned) table is specified. - This option cannot be used inside a transaction block, or from a function, - procedure, or DO block. - - - + + + The table is a system catalog or a TOAST table. + + - - boolean - - - Specifies whether the selected option should be turned on or off. - You can write TRUE, ON, or - 1 to enable the option, and FALSE, - OFF, or 0 to disable it. The - boolean value can also - be omitted, in which case TRUE is assumed. - - - - - + + + The table's access method is not heap. + + - - Notes + + + The table is declared as a catalog table using the + user_catalog_table + storage parameter. + + - - To repack a table, one must have the MAINTAIN privilege - on the table. + + + REPACK is executed inside a transaction block. + + + + + + The max_repack_replication_slots + configuration parameter does not allow for the creation of an + additional replication slot. + + + - - - REPACK refuses to process a table on which an invalid - index exists. Such indexes must be dropped or reindexed by the user ahead - of time. - - - - While REPACK is running, the is temporarily changed to pg_catalog, - pg_temp. - - - - Each backend running REPACK will report its progress - in the pg_stat_progress_repack view. See - for details. - - - - Repacking a partitioned table repacks each of its partitions. If an index - is specified, each partition is repacked using the partition of that - index. REPACK on a partitioned table cannot be executed - inside a transaction block. - - +