mirror of
https://github.com/postgres/postgres.git
synced 2025-09-02 04:21:28 +03:00
Report progress of CREATE INDEX operations
This uses the progress reporting infrastructure added by c16dc1aca5
,
adding support for CREATE INDEX and CREATE INDEX CONCURRENTLY.
There are two pieces to this: one is index-AM-agnostic, and the other is
AM-specific. The latter is fairly elaborate for btrees, including
reportage for parallel index builds and the separate phases that btree
index creation uses; other index AMs, which are much simpler in their
building procedures, have simplistic reporting only, but that seems
sufficient, at least for non-concurrent builds.
The index-AM-agnostic part is fairly complete, providing insight into
the CONCURRENTLY wait phases as well as block-based progress during the
index validation table scan. (The index validation index scan requires
patching each AM, which has not been included here.)
Reviewers: Rahila Syed, Pavan Deolasee, Tatsuro Yamada
Discussion: https://postgr.es/m/20181220220022.mg63bhk26zdpvmcj@alvherre.pgsql
This commit is contained in:
@@ -108,6 +108,9 @@ typedef bool (*amproperty_function) (Oid index_oid, int attno,
|
||||
IndexAMProperty prop, const char *propname,
|
||||
bool *res, bool *isnull);
|
||||
|
||||
/* name of phase as used in progress reporting */
|
||||
typedef char *(*ambuildphasename_function) (int64 phasenum);
|
||||
|
||||
/* validate definition of an opclass for this AM */
|
||||
typedef bool (*amvalidate_function) (Oid opclassoid);
|
||||
|
||||
@@ -213,6 +216,7 @@ typedef struct IndexAmRoutine
|
||||
amcostestimate_function amcostestimate;
|
||||
amoptions_function amoptions;
|
||||
amproperty_function amproperty; /* can be NULL */
|
||||
ambuildphasename_function ambuildphasename; /* can be NULL */
|
||||
amvalidate_function amvalidate;
|
||||
ambeginscan_function ambeginscan;
|
||||
amrescan_function amrescan;
|
||||
|
@@ -45,6 +45,7 @@ typedef struct IndexVacuumInfo
|
||||
{
|
||||
Relation index; /* the index being vacuumed */
|
||||
bool analyze_only; /* ANALYZE (without any actual vacuum) */
|
||||
bool report_progress; /* emit progress.h status reports */
|
||||
bool estimated_count; /* num_heap_tuples is an estimate */
|
||||
int message_level; /* ereport level for progress messages */
|
||||
double num_heap_tuples; /* tuples remaining in heap */
|
||||
|
@@ -671,6 +671,16 @@ typedef BTScanOpaqueData *BTScanOpaque;
|
||||
#define SK_BT_DESC (INDOPTION_DESC << SK_BT_INDOPTION_SHIFT)
|
||||
#define SK_BT_NULLS_FIRST (INDOPTION_NULLS_FIRST << SK_BT_INDOPTION_SHIFT)
|
||||
|
||||
/*
|
||||
* Constant definition for progress reporting. Phase numbers must match
|
||||
* btbuildphasename.
|
||||
*/
|
||||
/* PROGRESS_CREATEIDX_SUBPHASE_INITIALIZE is 1 (see progress.h) */
|
||||
#define PROGRESS_BTREE_PHASE_INDEXBUILD_TABLESCAN 2
|
||||
#define PROGRESS_BTREE_PHASE_PERFORMSORT_1 3
|
||||
#define PROGRESS_BTREE_PHASE_PERFORMSORT_2 4
|
||||
#define PROGRESS_BTREE_PHASE_LEAF_LOAD 5
|
||||
|
||||
/*
|
||||
* external entry points for btree, in nbtree.c
|
||||
*/
|
||||
@@ -784,6 +794,7 @@ extern bytea *btoptions(Datum reloptions, bool validate);
|
||||
extern bool btproperty(Oid index_oid, int attno,
|
||||
IndexAMProperty prop, const char *propname,
|
||||
bool *res, bool *isnull);
|
||||
extern char *btbuildphasename(int64 phasenum);
|
||||
extern IndexTuple _bt_truncate(Relation rel, IndexTuple lastleft,
|
||||
IndexTuple firstright, BTScanInsert itup_key);
|
||||
extern int _bt_keep_natts_fast(Relation rel, IndexTuple lastleft,
|
||||
|
@@ -507,6 +507,7 @@ typedef struct TableAmRoutine
|
||||
struct IndexInfo *index_nfo,
|
||||
bool allow_sync,
|
||||
bool anyvisible,
|
||||
bool progress,
|
||||
BlockNumber start_blockno,
|
||||
BlockNumber end_blockno,
|
||||
IndexBuildCallback callback,
|
||||
@@ -1369,6 +1370,8 @@ table_scan_analyze_next_tuple(TableScanDesc scan, TransactionId OldestXmin,
|
||||
* so here because the AM might reject some of the tuples for its own reasons,
|
||||
* such as being unable to store NULLs.
|
||||
*
|
||||
* If 'progress', the PROGRESS_SCAN_BLOCKS_TOTAL counter is updated when
|
||||
* starting the scan, and PROGRESS_SCAN_BLOCKS_DONE is updated as we go along.
|
||||
*
|
||||
* A side effect is to set indexInfo->ii_BrokenHotChain to true if we detect
|
||||
* any potentially broken HOT chains. Currently, we set this if there are any
|
||||
@@ -1382,6 +1385,7 @@ table_index_build_scan(Relation heap_rel,
|
||||
Relation index_rel,
|
||||
struct IndexInfo *index_nfo,
|
||||
bool allow_sync,
|
||||
bool progress,
|
||||
IndexBuildCallback callback,
|
||||
void *callback_state,
|
||||
TableScanDesc scan)
|
||||
@@ -1391,6 +1395,7 @@ table_index_build_scan(Relation heap_rel,
|
||||
index_nfo,
|
||||
allow_sync,
|
||||
false,
|
||||
progress,
|
||||
0,
|
||||
InvalidBlockNumber,
|
||||
callback,
|
||||
@@ -1414,6 +1419,7 @@ table_index_build_range_scan(Relation heap_rel,
|
||||
struct IndexInfo *index_nfo,
|
||||
bool allow_sync,
|
||||
bool anyvisible,
|
||||
bool progress,
|
||||
BlockNumber start_blockno,
|
||||
BlockNumber numblocks,
|
||||
IndexBuildCallback callback,
|
||||
@@ -1425,6 +1431,7 @@ table_index_build_range_scan(Relation heap_rel,
|
||||
index_nfo,
|
||||
allow_sync,
|
||||
anyvisible,
|
||||
progress,
|
||||
start_blockno,
|
||||
numblocks,
|
||||
callback,
|
||||
|
@@ -53,6 +53,6 @@
|
||||
*/
|
||||
|
||||
/* yyyymmddN */
|
||||
#define CATALOG_VERSION_NO 201904011
|
||||
#define CATALOG_VERSION_NO 201904021
|
||||
|
||||
#endif
|
||||
|
@@ -924,6 +924,10 @@
|
||||
proname => 'pg_index_column_has_property', provolatile => 's',
|
||||
prorettype => 'bool', proargtypes => 'regclass int4 text',
|
||||
prosrc => 'pg_index_column_has_property' },
|
||||
{ oid => '676', descr => 'return name of given index build phase',
|
||||
proname => 'pg_indexam_progress_phasename', provolatile => 'i',
|
||||
prorettype => 'text', proargtypes => 'oid int8',
|
||||
prosrc => 'pg_indexam_progress_phasename' },
|
||||
|
||||
{ oid => '339',
|
||||
proname => 'poly_same', prorettype => 'bool',
|
||||
@@ -5122,9 +5126,9 @@
|
||||
proname => 'pg_stat_get_progress_info', prorows => '100', proretset => 't',
|
||||
provolatile => 's', proparallel => 'r', prorettype => 'record',
|
||||
proargtypes => 'text',
|
||||
proallargtypes => '{text,int4,oid,oid,int8,int8,int8,int8,int8,int8,int8,int8,int8,int8}',
|
||||
proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o}',
|
||||
proargnames => '{cmdtype,pid,datid,relid,param1,param2,param3,param4,param5,param6,param7,param8,param9,param10}',
|
||||
proallargtypes => '{text,int4,oid,oid,int8,int8,int8,int8,int8,int8,int8,int8,int8,int8,int8,int8,int8,int8,int8,int8,int8,int8,int8,int8}',
|
||||
proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
|
||||
proargnames => '{cmdtype,pid,datid,relid,param1,param2,param3,param4,param5,param6,param7,param8,param9,param10,param11,param12,param13,param14,param15,param16,param17,param18,param19,param20}',
|
||||
prosrc => 'pg_stat_get_progress_info' },
|
||||
{ oid => '3099',
|
||||
descr => 'statistics: information about currently active replication',
|
||||
|
@@ -44,7 +44,7 @@
|
||||
#define PROGRESS_CLUSTER_HEAP_BLKS_SCANNED 6
|
||||
#define PROGRESS_CLUSTER_INDEX_REBUILD_COUNT 7
|
||||
|
||||
/* Phases of cluster (as dvertised via PROGRESS_CLUSTER_PHASE) */
|
||||
/* Phases of cluster (as advertised via PROGRESS_CLUSTER_PHASE) */
|
||||
#define PROGRESS_CLUSTER_PHASE_SEQ_SCAN_HEAP 1
|
||||
#define PROGRESS_CLUSTER_PHASE_INDEX_SCAN_HEAP 2
|
||||
#define PROGRESS_CLUSTER_PHASE_SORT_TUPLES 3
|
||||
@@ -57,4 +57,39 @@
|
||||
#define PROGRESS_CLUSTER_COMMAND_CLUSTER 1
|
||||
#define PROGRESS_CLUSTER_COMMAND_VACUUM_FULL 2
|
||||
|
||||
/* Progress parameters for CREATE INDEX */
|
||||
/* 3, 4 and 5 reserved for "waitfor" metrics */
|
||||
#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_TUPLES_TOTAL 11
|
||||
#define PROGRESS_CREATEIDX_TUPLES_DONE 12
|
||||
#define PROGRESS_CREATEIDX_PARTITIONS_TOTAL 13
|
||||
#define PROGRESS_CREATEIDX_PARTITIONS_DONE 14
|
||||
/* 15 and 16 reserved for "block number" metrics */
|
||||
|
||||
/* Phases of CREATE INDEX (as advertised via PROGRESS_CREATEIDX_PHASE) */
|
||||
#define PROGRESS_CREATEIDX_PHASE_WAIT_1 1
|
||||
#define PROGRESS_CREATEIDX_PHASE_BUILD 2
|
||||
#define PROGRESS_CREATEIDX_PHASE_WAIT_2 3
|
||||
#define PROGRESS_CREATEIDX_PHASE_VALIDATE_IDXSCAN 4
|
||||
#define PROGRESS_CREATEIDX_PHASE_VALIDATE_SORT 5
|
||||
#define PROGRESS_CREATEIDX_PHASE_VALIDATE_TABLESCAN 6
|
||||
#define PROGRESS_CREATEIDX_PHASE_WAIT_3 7
|
||||
|
||||
/*
|
||||
* Subphases of CREATE INDEX, for index_build.
|
||||
*/
|
||||
#define PROGRESS_CREATEIDX_SUBPHASE_INITIALIZE 1
|
||||
/* Additional phases are defined by each AM */
|
||||
|
||||
/* Lock holder wait counts */
|
||||
#define PROGRESS_WAITFOR_TOTAL 3
|
||||
#define PROGRESS_WAITFOR_DONE 4
|
||||
#define PROGRESS_WAITFOR_CURRENT_PID 5
|
||||
|
||||
/* Block numbers in a generic relation scan */
|
||||
#define PROGRESS_SCAN_BLOCKS_TOTAL 15
|
||||
#define PROGRESS_SCAN_BLOCKS_DONE 16
|
||||
|
||||
#endif
|
||||
|
@@ -951,10 +951,11 @@ typedef enum ProgressCommandType
|
||||
{
|
||||
PROGRESS_COMMAND_INVALID,
|
||||
PROGRESS_COMMAND_VACUUM,
|
||||
PROGRESS_COMMAND_CLUSTER
|
||||
PROGRESS_COMMAND_CLUSTER,
|
||||
PROGRESS_COMMAND_CREATE_INDEX
|
||||
} ProgressCommandType;
|
||||
|
||||
#define PGSTAT_NUM_PROGRESS_PARAM 10
|
||||
#define PGSTAT_NUM_PROGRESS_PARAM 20
|
||||
|
||||
/* ----------
|
||||
* Shared-memory data structures
|
||||
|
@@ -78,8 +78,8 @@ extern void XactLockTableWait(TransactionId xid, Relation rel,
|
||||
extern bool ConditionalXactLockTableWait(TransactionId xid);
|
||||
|
||||
/* Lock VXIDs, specified by conflicting locktags */
|
||||
extern void WaitForLockers(LOCKTAG heaplocktag, LOCKMODE lockmode);
|
||||
extern void WaitForLockersMultiple(List *locktags, LOCKMODE lockmode);
|
||||
extern void WaitForLockers(LOCKTAG heaplocktag, LOCKMODE lockmode, bool progress);
|
||||
extern void WaitForLockersMultiple(List *locktags, LOCKMODE lockmode, bool progress);
|
||||
|
||||
/* Lock an XID for tuple insertion (used to wait for an insertion to finish) */
|
||||
extern uint32 SpeculativeInsertionLockAcquire(TransactionId xid);
|
||||
|
@@ -544,7 +544,7 @@ extern bool LockHeldByMe(const LOCKTAG *locktag, LOCKMODE lockmode);
|
||||
extern bool LockHasWaiters(const LOCKTAG *locktag,
|
||||
LOCKMODE lockmode, bool sessionLock);
|
||||
extern VirtualTransactionId *GetLockConflicts(const LOCKTAG *locktag,
|
||||
LOCKMODE lockmode);
|
||||
LOCKMODE lockmode, int *countp);
|
||||
extern void AtPrepare_Locks(void);
|
||||
extern void PostPrepare_Locks(TransactionId xid);
|
||||
extern int LockCheckConflicts(LockMethod lockMethodTable,
|
||||
|
Reference in New Issue
Block a user