|
pg_stat_progress_create_indexpg_stat_progress_create_index
- One row for each backend running CREATE INDEX, showing
+ One row for each backend running CREATE INDEX or REINDEX, showing
current progress.
See .
CREATE INDEX Progress Reporting
- Whenever CREATE INDEX is running, the
+ Whenever CREATE INDEX or REINDEX is running, the
pg_stat_progress_create_index view will contain
one row for each backend that is currently creating indexes. The tables
below describe the information that will be reported and provide information
oid
OID of the table on which the index is being created.
+ |
+ index_relid
+ oid
+ OID of the index being created or reindexed. During a
+ non-concurrent CREATE INDEX, this is 0.
+
|
phase
text
|
initializing
- CREATE INDEX is preparing to create the index. This
+ CREATE INDEX or REINDEX is preparing to create the index. This
phase is expected to be very brief.
|
- waiting for old snapshots
+ waiting for writers before build
- CREATE INDEX CONCURRENTLY is waiting for transactions
- that can potentially see the table to release their snapshots.
+ CREATE INDEX CONCURRENTLY or REINDEX CONCURRENTLY is waiting for transactions
+ with write locks that can potentially see the table to finish.
This phase is skipped when not in concurrent mode.
Columns lockers_total, lockers_done
and current_locker_pid contain the progress
|
- waiting for writer snapshots
+ waiting for writers before validation
- CREATE INDEX CONCURRENTLY is waiting for transactions
- that can potentially write into the table to release their snapshots.
+ CREATE INDEX CONCURRENTLY or REINDEX CONCURRENTLY is waiting for transactions
+ with write locks that can potentially write into the table to finish.
This phase is skipped when not in concurrent mode.
Columns lockers_total, lockers_done
and current_locker_pid contain the progress
|
- waiting for reader snapshots
+ waiting for old snapshots
- CREATE INDEX CONCURRENTLY is waiting for transactions
+ CREATE INDEX CONCURRENTLY or REINDEX CONCURRENTLY is waiting for transactions
that can potentially see the table to release their snapshots. This
phase is skipped when not in concurrent mode.
Columns lockers_total, lockers_done
information for this phase.
+ |
+ waiting for readers before marking dead
+
+ REINDEX CONCURRENTLY is waiting for transactions
+ with read locks on the table to finish, before marking the old index dead.
+ This phase is skipped when not in concurrent mode.
+ Columns lockers_total, lockers_done
+ and current_locker_pid contain the progress
+ information for this phase.
+
+
+ |
+ waiting for readers before dropping
+
+ REINDEX CONCURRENTLY is waiting for transactions
+ with read locks on the table to finish, before dropping the old index.
+ This phase is skipped when not in concurrent mode.
+ Columns lockers_total, lockers_done
+ and current_locker_pid contain the progress
+ information for this phase.
+
+
heapId = IndexGetRelation(indexId, false);
heapRelation = table_open(heapId, ShareLock);
+ pgstat_progress_start_command(PROGRESS_COMMAND_CREATE_INDEX,
+ heapId);
+ pgstat_progress_update_param(PROGRESS_CREATEIDX_INDEX_OID,
+ indexId);
+
/*
* Open the target index relation and get an exclusive lock on it, to
* ensure that no one else is touching this particular index.
*/
iRel = index_open(indexId, AccessExclusiveLock);
+ pgstat_progress_update_param(PROGRESS_CREATEIDX_ACCESS_METHOD_OID,
+ iRel->rd_rel->relam);
+
/*
* The case of reindexing partitioned tables and indexes is handled
* differently by upper layers, so this case shouldn't arise.
errdetail_internal("%s",
pg_rusage_show(&ru0))));
+ pgstat_progress_end_command();
+
/* Close rels, but keep locks */
index_close(iRel, NoLock);
table_close(heapRelation, NoLock);
SELECT
S.pid AS pid, S.datid AS datid, D.datname AS datname,
S.relid AS relid,
+ CAST(S.param7 AS oid) AS index_relid,
CASE S.param10 WHEN 0 THEN 'initializing'
- WHEN 1 THEN 'waiting for old snapshots'
+ WHEN 1 THEN 'waiting for writers before build'
WHEN 2 THEN 'building index' ||
COALESCE((': ' || pg_indexam_progress_phasename(S.param9::oid, S.param11)),
'')
- WHEN 3 THEN 'waiting for writer snapshots'
+ WHEN 3 THEN 'waiting for writers before validation'
WHEN 4 THEN 'index validation: scanning index'
WHEN 5 THEN 'index validation: sorting tuples'
WHEN 6 THEN 'index validation: scanning table'
- WHEN 7 THEN 'waiting for reader snapshots'
+ WHEN 7 THEN 'waiting for old snapshots'
+ WHEN 8 THEN 'waiting for readers before marking dead'
+ WHEN 9 THEN 'waiting for readers before dropping'
END as phase,
S.param4 AS lockers_total,
S.param5 AS lockers_done,
pgstat_progress_start_command(PROGRESS_COMMAND_CREATE_INDEX,
relationId);
+ /*
+ * No index OID to report yet
+ */
+ pgstat_progress_update_param(PROGRESS_CREATEIDX_INDEX_OID,
+ InvalidOid);
+
/*
* count key attributes in index
*/
CommitTransactionCommand();
StartTransactionCommand();
+ /*
+ * The index is now visible, so we can report the OID.
+ */
+ pgstat_progress_update_param(PROGRESS_CREATEIDX_INDEX_OID,
+ indexRelationId);
+
/*
* Phase 2 of concurrent index build (see comments for validate_index()
* for an overview of how this works)
heapRel = table_open(indexRel->rd_index->indrelid,
ShareUpdateExclusiveLock);
+ pgstat_progress_start_command(PROGRESS_COMMAND_CREATE_INDEX,
+ RelationGetRelid(heapRel));
+ pgstat_progress_update_param(PROGRESS_CREATEIDX_INDEX_OID,
+ indexId);
+ pgstat_progress_update_param(PROGRESS_CREATEIDX_ACCESS_METHOD_OID,
+ indexRel->rd_rel->relam);
+
/* Choose a temporary relation name for the new index */
concurrentName = ChooseRelationName(get_rel_name(indexId),
NULL,
* DefineIndex() for more details.
*/
- WaitForLockersMultiple(lockTags, ShareLock, false);
+ pgstat_progress_update_param(PROGRESS_CREATEIDX_PHASE,
+ PROGRESS_CREATEIDX_PHASE_WAIT_1);
+ WaitForLockersMultiple(lockTags, ShareLock, true);
CommitTransactionCommand();
forboth(lc, indexIds, lc2, newIndexIds)
* for more details.
*/
- WaitForLockersMultiple(lockTags, ShareLock, false);
+ pgstat_progress_update_param(PROGRESS_CREATEIDX_PHASE,
+ PROGRESS_CREATEIDX_PHASE_WAIT_2);
+ WaitForLockersMultiple(lockTags, ShareLock, true);
CommitTransactionCommand();
foreach(lc, newIndexIds)
* before the reference snap was taken, we have to wait out any
* transactions that might have older snapshots.
*/
- WaitForOlderSnapshots(limitXmin, false);
+ pgstat_progress_update_param(PROGRESS_CREATEIDX_PHASE,
+ PROGRESS_CREATEIDX_PHASE_WAIT_3);
+ WaitForOlderSnapshots(limitXmin, true);
CommitTransactionCommand();
}
* index_drop() for more details.
*/
- WaitForLockersMultiple(lockTags, AccessExclusiveLock, false);
+ pgstat_progress_update_param(PROGRESS_CREATEIDX_PHASE,
+ PROGRESS_CREATEIDX_PHASE_WAIT_4);
+ WaitForLockersMultiple(lockTags, AccessExclusiveLock, true);
foreach(lc, indexIds)
{
* Drop the old indexes.
*/
- WaitForLockersMultiple(lockTags, AccessExclusiveLock, false);
+ pgstat_progress_update_param(PROGRESS_CREATEIDX_PHASE,
+ PROGRESS_CREATEIDX_PHASE_WAIT_4);
+ WaitForLockersMultiple(lockTags, AccessExclusiveLock, true);
PushActiveSnapshot(GetTransactionSnapshot());
MemoryContextDelete(private_context);
+ pgstat_progress_end_command();
+
return true;
}
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 201904071
+#define CATALOG_VERSION_NO 201904072
#endif
/* Progress parameters for CREATE INDEX */
/* 3, 4 and 5 reserved for "waitfor" metrics */
+#define PROGRESS_CREATEIDX_INDEX_OID 6
#define PROGRESS_CREATEIDX_ACCESS_METHOD_OID 8
#define PROGRESS_CREATEIDX_PHASE 9 /* AM-agnostic phase # */
#define PROGRESS_CREATEIDX_SUBPHASE 10 /* phase # filled by AM */
#define PROGRESS_CREATEIDX_PHASE_VALIDATE_SORT 5
#define PROGRESS_CREATEIDX_PHASE_VALIDATE_TABLESCAN 6
#define PROGRESS_CREATEIDX_PHASE_WAIT_3 7
+#define PROGRESS_CREATEIDX_PHASE_WAIT_4 8
+#define PROGRESS_CREATEIDX_PHASE_WAIT_5 9
/*
* Subphases of CREATE INDEX, for index_build.
s.datid,
d.datname,
s.relid,
+ (s.param7)::oid AS index_relid,
CASE s.param10
WHEN 0 THEN 'initializing'::text
- WHEN 1 THEN 'waiting for old snapshots'::text
+ WHEN 1 THEN 'waiting for writers before build'::text
WHEN 2 THEN ('building index'::text || COALESCE((': '::text || pg_indexam_progress_phasename((s.param9)::oid, s.param11)), ''::text))
- WHEN 3 THEN 'waiting for writer snapshots'::text
+ WHEN 3 THEN 'waiting for writers before validation'::text
WHEN 4 THEN 'index validation: scanning index'::text
WHEN 5 THEN 'index validation: sorting tuples'::text
WHEN 6 THEN 'index validation: scanning table'::text
- WHEN 7 THEN 'waiting for reader snapshots'::text
+ WHEN 7 THEN 'waiting for old snapshots'::text
+ WHEN 8 THEN 'waiting for readers before marking dead'::text
+ WHEN 9 THEN 'waiting for readers before dropping'::text
ELSE NULL::text
END AS phase,
s.param4 AS lockers_total,