Vacuum Processing in PostgreSQL: A Comprehensive Guide 🧹💻
Tags: postgres, beginners
Published: 2023-06-04 17:31:11

## 1. Introduction

Welcome to our detailed guide on vacuum processing in PostgreSQL! In this blog, we'll explore the importance of vacuum processing and its evolution in PostgreSQL. Vacuum processing is a crucial maintenance process that ensures the smooth operation of PostgreSQL databases. It involves removing dead tuples (rows) and freezing transaction ids to optimize database performance and prevent bloat. 

## 2. Vacuum Processing and Its Importance

Vacuum processing is an essential task in PostgreSQL to maintain database health and performance. It primarily focuses on two tasks: removing dead tuples and freezing transaction ids. Dead tuples are rows that are no longer needed and can be safely removed to reclaim storage space. Freezing transaction ids involves marking old transaction ids as frozen, preventing them from interfering with concurrent transactions. Both of these tasks play a vital role in maintaining the integrity and efficiency of PostgreSQL databases.

## 3. Types of Vacuum Modes

PostgreSQL provides two modes of vacuum processing: Concurrent VACUUM and Full VACUUM. Let's explore each mode in detail:

### 3.1 Concurrent VACUUM

Concurrent VACUUM, often referred to as VACUUM, removes dead tuples for each page of the table file. The advantage of this mode is that other transactions can still read the table while the vacuum process is running. It ensures minimal disruption to the normal operation of the database. 

### 3.2 Full VACUUM

Full VACUUM, on the other hand, removes dead tuples and defragments live tuples for the entire table file. While Full VACUUM provides a more thorough cleaning process, it locks the table, preventing other transactions from accessing it during the vacuum operation. Full VACUUM is typically used when the database requires intensive maintenance or when significant bloat is detected.

## 4. Evolution of Vacuum Processing in PostgreSQL

Over the years, vacuum processing in PostgreSQL has undergone significant improvements. In earlier versions, vacuuming had to be manually executed or scheduled using external tools. However, in 2005, the autovacuum daemon was introduced, automating the vacuum process and making it more efficient. Despite these advancements, vacuum processing has been relatively slower to evolve compared to other PostgreSQL functions.

## 5. Outline of Concurrent VACUUM

Let's dive deeper into the concurrent VACUUM process, which is the most commonly used mode in PostgreSQL. It involves several important tasks:

### 5.1 Removing Dead Tuples

The first block of the concurrent VACUUM process focuses on scanning all pages of the table to identify and remove dead tuples. Dead tuples are rows that are no longer required and can be safely deleted. This step helps reclaim storage space and optimize database performance.

### 5.2 Freezing Old Transaction IDs

In addition to removing dead tuples, the concurrent VACUUM process also freezes old transaction ids (txids) if necessary. Freezing transaction ids is crucial to prevent them from interfering with concurrent transactions and maintaining database consistency.

### 5.3 Removing Unnecessary Clog Files

During the vacuum process, PostgreSQL also removes unnecessary parts of the clog (commit log). This cleanup helps manage the storage space efficiently and ensures the integrity of transaction logs.

### 5.4 Autovacuum Daemon

The autovacuum daemon plays a vital role in the concurrent VACUUM process. It automatically manages and triggers vacuuming for tables based on predefined thresholds and configurations. The autovacuum daemon ensures continuous maintenance of the database without manual intervention.

### 6. Full VACUUM
Full VACUUM is a comprehensive vacuuming process that removes dead tuples and defragments live tuples in the entire table file. Unlike Concurrent VACUUM, Full VACUUM requires exclusive access to the table, preventing other transactions from accessing it during the process. Although Full VACUUM provides thorough maintenance, it can be a time-consuming operation due to scanning the entire table.

### 7. Parallel Option
Starting from version 13, the VACUUM command supports the PARALLEL option. This option allows vacuuming and cleaning index phases to run in parallel when multiple indexes are present. However, it's important to note that the parallel option is only applicable to the VACUUM command and not to autovacuum.

### 8. The First Block: Freeze Processing and Removing Index Tuples
The first block of vacuum processing focuses on freeze processing and removing index tuples pointing to dead tuples. PostgreSQL scans the target table to identify dead tuples and freeze old tuples, if possible. Once the scanning is complete, the index tuples referring to the dead tuples are removed. This step is known as the "cleanup stage" and can be resource-intensive. Starting from version 11, the cleanup stage's execution depends on the vacuum_cleanup_index_scale_factor configuration parameter for B-tree indexes.

### 9. The Second Block: Removing Dead Tuples and Updating FSM and VM
The second block of vacuum processing focuses on removing dead tuples and updating the Free Space Map (FSM) and Visibility Map (VM). Dead tuples are tuples that have become obsolete and can be safely removed from the database. The removal of dead tuples helps to free up space and optimize query performance.
In this block, PostgreSQL scans each page of the table and performs the following tasks:
1.	Remove dead tuples from the page.
2.	Reallocate live tuples within the page to repair fragmentation.
3.	Update the FSM and VM to reflect the changes.
Removing dead tuples and reallocating live tuples helps to reduce fragmentation and improve data locality within the table. The FSM keeps track of free space available on each page, while the VM indicates the visibility of pages and allows skipping pages without dead tuples during subsequent vacuum runs.
🔧 Tip: Removing dead tuples and updating the FSM and VM improves query performance by optimizing data storage and access.

### 10. The Third Block: Cleanup, Statistics Update, and Truncation
In the third block of vacuum processing, additional cleanup tasks are performed, along with updating statistics and truncating the last page if possible. Let's explore each task in detail:
1.	Cleanup: This step involves cleaning up indexes associated with the table being vacuumed. The index_vacuum_cleanup() function is used for this purpose.
2.	Truncation: If the last page of the table does not contain any tuples, it can be safely truncated from the table file. Truncation helps to reclaim disk space.
3.	Statistics Update: Vacuum processing updates various statistics related to the vacuum operation, such as the number of live and dead tuples, last vacuum time, and vacuum count. These statistics are crucial for monitoring the health and performance of the database.
By performing these tasks, vacuum processing ensures that the database remains in an optimized state, with accurate statistics reflecting the latest changes.

### 11. Post-processing: Updating Statistics and Removing Unnecessary Clog Files
After completing the vacuum processing for all the tables, post-processing steps are executed to finalize the operation. These steps involve updating statistics and system catalogs and removing unnecessary clog files.
1.	Updating Statistics: PostgreSQL updates various statistics related to vacuum processing. These statistics provide insights into the effectiveness of the vacuum operation and help in monitoring database performance.
2.	Removing Unnecessary Clog Files: The Command Logging (clog) files track transaction information in PostgreSQL. After vacuum processing, unnecessary parts of the clog files can be safely removed, freeing up disk space.
Updating statistics and removing unnecessary clog files ensure the database remains in an optimized state and helps in efficient future vacuum operations.

### 12. Visibility Map: Reducing Vacuum Processing Cost
🌍 The Visibility Map (VM) is a table-specific map that stores visibility information about individual pages in the table file. Each page's visibility status determines if it contains dead tuples. By consulting the VM, vacuum processing can skip pages without dead tuples, saving time and effort. The VM is composed of one or more 8 KB pages, stored with the 'vm' suffix. This optimization technique significantly improves the efficiency of vacuum processing.

#### Enhancement of the Visibility Map
 ✨ In version 9.6, the Visibility Map (VM) was further enhanced to boost the efficiency of freeze processing. The new VM not only indicates page visibility but also provides information about whether tuples are frozen or not. This enhancement allows for more targeted and precise freeze processing. By efficiently tracking frozen tuples, the VM helps minimize the overhead of freeze operations during vacuum processing, resulting in faster and more optimized performance.

#### Freeze Processing: Lazy Mode and Eager Mode 💤
 Freeze processing, a critical part of vacuum processing, can run in two modes: lazy mode and eager mode. In lazy mode, PostgreSQL scans only pages with dead tuples, leveraging the Visibility Map (VM) to skip unnecessary pages. This mode is efficient but might not fully freeze all tuples. On the other hand, eager mode scans all pages, regardless of tuple visibility, and performs comprehensive freeze processing. It updates system catalogs, removes unnecessary clog files, and ensures thorough tuple freezing.

### 13. Freeze Processing: Lazy Mode and Eager Mode

#### Lazy Mode 😴
 In lazy mode, freeze processing selectively scans pages with dead tuples, utilizing the information provided by the Visibility Map (VM). By calculating the freezeLimit txid based on the oldest transaction id (OldestXmin) and the vacuum_freeze_min_age configuration parameter, PostgreSQL determines which tuples to freeze. While this mode is efficient, it may not freeze all tuples if pages without dead tuples are skipped. However, it significantly reduces processing time and resource utilization.

#### Eager Mode⏩
 Eager mode compensates for the potential incompleteness of lazy mode by scanning all pages, regardless of tuple visibility. It ensures comprehensive freeze processing by examining and freezing all tuples in the tables. Eager mode also updates system catalogs and removes unnecessary files and pages of the clog, further optimizing the vacuum process. The decision to enter eager mode depends on the comparison between pg_database.datfrozenxid and OldestXmin minus the vacuum_freeze_table_age configuration parameter.

### Conclusion🔚 
Vacuum processing is a crucial aspect of PostgreSQL maintenance, but it can be a resource-intensive operation. However, with the introduction of the Visibility Map (VM) and subsequent enhancements, PostgreSQL has significantly improved the efficiency of vacuum processing. By leveraging the VM to skip unnecessary scans and employing both lazy and eager modes for freeze processing, PostgreSQL achieves faster and more optimized vacuum operations. These optimizations reduce processing time, minimize resource utilization, and contribute to a smoother and more efficient PostgreSQL experience.