PARALLEL
- Perform vacuum index and cleanup index phases of VACUUM
+ Perform index vacuum and index cleanup phases of VACUUM
in parallel using integer
- background workers (for the detail of each vacuum phases , please
+ background workers (for the details of each vacuum phase , please
refer to ). If the
- PARALLEL option is omitted, then
- VACUUM decides the number of workers based on number
- of indexes that support parallel vacuum operation on the relation which
- is further limited by linkend="guc-max-parallel-workers-maintenance"/>.
- The index can participate in a parallel vacuum if and only if the size
+ PARALLEL option is omitted, then the number of workers
+ is determined based on the number of indexes that support parallel vacuum
+ operation on the relation, and is further limited by
+ linkend="guc-max-parallel-workers-maintenance"/>.
+ An index can participate in parallel vacuum if and only if the size
of the index is more than .
Please note that it is not guaranteed that the number of parallel workers
specified in integer will
workers than specified, or even with no workers at all. Only one worker
can be used per index. So parallel workers are launched only when there
are at least 2 indexes in the table. Workers for
- vacuum launches before starting each phase and exit at the end of
+ vacuum are launched before the start of each phase and exit at the end of
the phase. These behaviors might change in a future release. This
option can't be used with the FULL option.
- The PARALLEL option is used only for vacuum purpose.
- Even if this option is specified with ANALYZE option
+ The PARALLEL option is used only for vacuum purposes .
+ If this option is specified with the ANALYZE option,
it does not affect ANALYZE .
VACUUM causes a substantial increase in I/O traffic,
which might cause poor performance for other active sessions. Therefore,
it is sometimes advisable to use the cost-based vacuum delay feature. For
- parallel vacuum, each worker sleeps proportional to the work done by that
+ parallel vacuum, each worker sleeps in proportion to the work done by that
worker. See for
details.
* live tuples in the index vacuum case or the new live tuples in the
* index cleanup case.
*
- * estimated_count is true if the reltuples is an estimated value.
+ * estimated_count is true if reltuples is an estimated value.
*/
double reltuples;
bool estimated_count;
/*
* Number of active parallel workers. This is used for computing the
- * minimum threshold of the vacuum cost balance for a worker to go for the
- * delay.
+ * minimum threshold of the vacuum cost balance before a worker sleeps for
+ * cost-based delay.
*/
pg_atomic_uint32 active_nworkers;
* to reclaim dead line pointers.
*
* If the table has at least two indexes, we execute both index vacuum
- * and index cleanup with parallel workers unless the parallel vacuum is
+ * and index cleanup with parallel workers unless parallel vacuum is
* disabled. In a parallel vacuum, we enter parallel mode and then
* create both the parallel context and the DSM segment before starting
* heap scan so that we can record dead tuples to the DSM segment. All
vacrelstats->latestRemovedXid = InvalidTransactionId;
/*
- * Initialize the state for a parallel vacuum. As of now, only one worker
- * can be used for an index, so we invoke parallelism only if there are at
+ * Initialize state for a parallel vacuum. As of now, only one worker can
+ * be used for an index, so we invoke parallelism only if there are at
* least two indexes on a table.
*/
if (params->nworkers >= 0 && vacrelstats->useindex && nindexes > 1)
}
/*
- * Allocate the space for dead tuples in case the parallel vacuum is not
+ * Allocate the space for dead tuples in case parallel vacuum is not
* initialized.
*/
if (!ParallelVacuumIsActive(lps))
shared_indstats = get_indstats(lvshared, idx);
/*
- * Skip processing indexes that does n't participate in parallel
+ * Skip processing indexes that don't participate in parallel
* operation
*/
if (shared_indstats == NULL ||
/*
* Copy the index bulk-deletion result returned from ambulkdelete and
- * amvacuumcleanup to the DSM segment if it's the first time to get it
- * from them, because they allocate it locally and it's possible that an
- * index will be vacuumed by the different vacuum process at the next
- * time. The copying of the result normally happens only after the first
- * time of index vacuuming. From the second time, we pass the result on
- * the DSM segment so that they the n update it directly.
+ * amvacuumcleanup to the DSM segment if it's the first cycle because they
+ * allocate locally and it's possible that an index will be vacuumed by a
+ * different vacuum process the next cycle. Copying the result normally
+ * happens only the first time an index is vacuumed. For any additional
+ * vacuum pass, we directly point to the result on the DSM segment and
+ * pass it to vacuum index APIs so that workers ca n update it directly.
*
* Since all vacuum workers write the bulk-deletion result at different
* slots we can write them without locking.
shared_indstats->updated = true;
/*
- * Now that the stats[idx] points to the DSM segment, we don't need
- * the locally allocated results.
+ * Now that stats[idx] points to the DSM segment, we don't need the
+ * locally allocated results.
*/
pfree(*stats);
*stats = bulkdelete_res;
* lazy_cleanup_index() -- do post-vacuum cleanup for one index relation.
*
* reltuples is the number of heap tuples and estimated_count is true
- * if the reltuples is an estimated value.
+ * if reltuples is an estimated value.
*/
static void
lazy_cleanup_index(Relation indrel,
/*
* Compute the number of parallel worker processes to request. Both index
* vacuum and index cleanup can be executed with parallel workers. The index
- * is eligible for parallel vacuum iff it' s size is greater than
+ * is eligible for parallel vacuum iff its size is greater than
* min_parallel_index_scan_size as invoking workers for very small indexes
- * can hurt the performance.
+ * can hurt performance.
*
* nrequested is the number of parallel workers that user requested. If
* nrequested is 0, we compute the parallel degree based on nindexes, that is
int i;
/*
- * We don't allow to perform parallel operation in standalone backend or
+ * We don't allow performing parallel operation in standalone backend or
* when parallelism is disabled.
*/
if (!IsUnderPostmaster || max_parallel_maintenance_workers == 0)
if (!can_parallel_vacuum[i])
continue;
- /* Set NOT NULL as this index do support parallelism */
+ /* Set NOT NULL as this index does support parallelism */
lvshared->bitmap[i >> 3] |= 1 << (i & 0x07);
}
}
/*
- * Update index statistics in pg_class if the statistics is accurate.
+ * Update index statistics in pg_class if the statistics are accurate.
*/
static void
update_index_statistics(Relation *Irel, IndexBulkDeleteResult **stats,
/*
* This function prepares and returns parallel vacuum state if we can launch
- * even one worker. This function is responsible to enter parallel mode,
+ * even one worker. This function is responsible for entering parallel mode,
* create a parallel context, and then initialize the DSM segment.
*/
static LVParallelState *
/*
* Destroy the parallel context, and end parallel mode.
*
- * Since writes are not allowed during the parallel mode, so we copy the
- * updated index statistics from DSM in local memory and then later use that
+ * Since writes are not allowed during parallel mode, copy the
+ * updated index statistics from DSM into local memory and then later use that
* to update the index statistics. One might think that we can exit from
* parallel mode, update the index statistics and then destroy parallel
* context, but that won't be safe (see ExitParallelMode).
* Perform work within a launched parallel process.
*
* Since parallel vacuum workers perform only index vacuum or index cleanup,
- * we don't need to report the progress information.
+ * we don't need to report progress information.
*/
void
parallel_vacuum_main(dsm_segment *seg, shm_toc *toc)
/*
* Computes the vacuum delay for parallel workers.
*
- * The basic idea of a cost-based vacuum delay for parallel vacuum is to allow
- * each worker to sleep proportional to the work done by it . We achieve this
+ * The basic idea of a cost-based delay for parallel vacuum is to allow each
+ * worker to sleep in proportion to the share of work it's done . We achieve this
* by allowing all parallel vacuum workers including the leader process to
* have a shared view of cost related parameters (mainly VacuumCostBalance).
* We allow each worker to update it as and when it has incurred any cost and
* then based on that decide whether it needs to sleep. We compute the time
* to sleep for a worker based on the cost it has incurred
* (VacuumCostBalanceLocal) and then reduce the VacuumSharedCostBalance by
- * that amount. This avoids letting the workers sleep who have done less or
- * no I/O as compared to other workers and therefore can ensure that workers
- * who are doing more I/O got throttled more.
+ * that amount. This avoids putting to sleep those workers which have done less
+ * I/O than other workers and therefore ensure that workers
+ * which are doing more I/O got throttled more.
*
- * We allow any worker to sleep only if it has performed the I/O above a
- * certain threshold, which is calculated based on the number of active
- * workers (VacuumActiveNWorkers), and the overall cost balance is more than
- * VacuumCostLimit set by the system. The t esting reveals that we achieve
- * the required throttling if we allow a worker that has done more than 50%
+ * We allow a worker to sleep only if it has performed I/O above a certain
+ * threshold, which is calculated based on the number of active workers
+ * (VacuumActiveNWorkers), and the overall cost balance is more than
+ * VacuumCostLimit set by the system. Testing reveals that we achieve
+ * the required throttling if we force a worker that has done more than 50%
* of its share of work to sleep.
*/
static double