diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/catalog/index.c | 9 | ||||
-rw-r--r-- | src/backend/catalog/system_views.sql | 27 | ||||
-rw-r--r-- | src/backend/commands/cluster.c | 88 | ||||
-rw-r--r-- | src/backend/utils/adt/pgstatfuncs.c | 2 | ||||
-rw-r--r-- | src/include/catalog/catversion.h | 2 | ||||
-rw-r--r-- | src/include/commands/progress.h | 23 | ||||
-rw-r--r-- | src/include/pgstat.h | 3 | ||||
-rw-r--r-- | src/test/regress/expected/rules.out | 28 |
8 files changed, 180 insertions, 2 deletions
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index cb2c0010171..d2e284f6de6 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -52,6 +52,7 @@ #include "catalog/storage.h" #include "commands/tablecmds.h" #include "commands/event_trigger.h" +#include "commands/progress.h" #include "commands/trigger.h" #include "executor/executor.h" #include "miscadmin.h" @@ -59,6 +60,7 @@ #include "nodes/nodeFuncs.h" #include "optimizer/optimizer.h" #include "parser/parser.h" +#include "pgstat.h" #include "rewrite/rewriteManip.h" #include "storage/bufmgr.h" #include "storage/lmgr.h" @@ -3846,6 +3848,7 @@ reindex_relation(Oid relid, int flags, int options) List *indexIds; bool is_pg_class; bool result; + int i; /* * Open and lock the relation. ShareLock is sufficient since we only need @@ -3933,6 +3936,7 @@ reindex_relation(Oid relid, int flags, int options) /* Reindex all the indexes. */ doneIndexes = NIL; + i = 1; foreach(indexId, indexIds) { Oid indexOid = lfirst_oid(indexId); @@ -3950,6 +3954,11 @@ reindex_relation(Oid relid, int flags, int options) if (is_pg_class) doneIndexes = lappend_oid(doneIndexes, indexOid); + + /* Set index rebuild count */ + pgstat_progress_update_param(PROGRESS_CLUSTER_INDEX_REBUILD_COUNT, + i); + i++; } } PG_CATCH(); diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql index d962648bc5c..b89df70653e 100644 --- a/src/backend/catalog/system_views.sql +++ b/src/backend/catalog/system_views.sql @@ -907,6 +907,33 @@ CREATE VIEW pg_stat_progress_vacuum AS FROM pg_stat_get_progress_info('VACUUM') AS S LEFT JOIN pg_database D ON S.datid = D.oid; +CREATE VIEW pg_stat_progress_cluster AS + SELECT + S.pid AS pid, + S.datid AS datid, + D.datname AS datname, + S.relid AS relid, + CASE S.param1 WHEN 1 THEN 'CLUSTER' + WHEN 2 THEN 'VACUUM FULL' + END AS command, + CASE S.param2 WHEN 0 THEN 'initializing' + WHEN 1 THEN 'seq scanning heap' + WHEN 2 THEN 'index scanning heap' + WHEN 3 THEN 'sorting tuples' + WHEN 4 THEN 'writing new heap' + WHEN 5 THEN 'swapping relation files' + WHEN 6 THEN 'rebuilding index' + WHEN 7 THEN 'performing final cleanup' + END AS phase, + S.param3 AS cluster_index_relid, + S.param4 AS heap_tuples_scanned, + S.param5 AS heap_tuples_written, + S.param6 AS heap_blks_total, + S.param7 AS heap_blks_scanned, + S.param8 AS index_rebuild_count + FROM pg_stat_get_progress_info('CLUSTER') AS S + LEFT JOIN pg_database D ON S.datid = D.oid; + CREATE VIEW pg_user_mappings AS SELECT U.oid AS umid, diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c index 3e2a807640f..205070b83d2 100644 --- a/src/backend/commands/cluster.c +++ b/src/backend/commands/cluster.c @@ -36,10 +36,12 @@ #include "catalog/objectaccess.h" #include "catalog/toasting.h" #include "commands/cluster.h" +#include "commands/progress.h" #include "commands/tablecmds.h" #include "commands/vacuum.h" #include "miscadmin.h" #include "optimizer/optimizer.h" +#include "pgstat.h" #include "storage/bufmgr.h" #include "storage/lmgr.h" #include "storage/predicate.h" @@ -276,6 +278,14 @@ cluster_rel(Oid tableOid, Oid indexOid, int options) /* Check for user-requested abort. */ CHECK_FOR_INTERRUPTS(); + pgstat_progress_start_command(PROGRESS_COMMAND_CLUSTER, tableOid); + if (OidIsValid(indexOid)) + pgstat_progress_update_param(PROGRESS_CLUSTER_COMMAND, + PROGRESS_CLUSTER_COMMAND_CLUSTER); + else + pgstat_progress_update_param(PROGRESS_CLUSTER_COMMAND, + PROGRESS_CLUSTER_COMMAND_VACUUM_FULL); + /* * We grab exclusive access to the target rel and index for the duration * of the transaction. (This is redundant for the single-transaction @@ -286,7 +296,10 @@ cluster_rel(Oid tableOid, Oid indexOid, int options) /* If the table has gone away, we can skip processing it */ if (!OldHeap) + { + pgstat_progress_end_command(); return; + } /* * Since we may open a new transaction for each relation, we have to check @@ -305,6 +318,7 @@ cluster_rel(Oid tableOid, Oid indexOid, int options) if (!pg_class_ownercheck(tableOid, GetUserId())) { relation_close(OldHeap, AccessExclusiveLock); + pgstat_progress_end_command(); return; } @@ -319,6 +333,7 @@ cluster_rel(Oid tableOid, Oid indexOid, int options) if (RELATION_IS_OTHER_TEMP(OldHeap)) { relation_close(OldHeap, AccessExclusiveLock); + pgstat_progress_end_command(); return; } @@ -330,6 +345,7 @@ cluster_rel(Oid tableOid, Oid indexOid, int options) if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(indexOid))) { relation_close(OldHeap, AccessExclusiveLock); + pgstat_progress_end_command(); return; } @@ -340,6 +356,7 @@ cluster_rel(Oid tableOid, Oid indexOid, int options) if (!HeapTupleIsValid(tuple)) /* probably can't happen */ { relation_close(OldHeap, AccessExclusiveLock); + pgstat_progress_end_command(); return; } indexForm = (Form_pg_index) GETSTRUCT(tuple); @@ -347,6 +364,7 @@ cluster_rel(Oid tableOid, Oid indexOid, int options) { ReleaseSysCache(tuple); relation_close(OldHeap, AccessExclusiveLock); + pgstat_progress_end_command(); return; } ReleaseSysCache(tuple); @@ -401,6 +419,7 @@ cluster_rel(Oid tableOid, Oid indexOid, int options) !RelationIsPopulated(OldHeap)) { relation_close(OldHeap, AccessExclusiveLock); + pgstat_progress_end_command(); return; } @@ -416,6 +435,8 @@ cluster_rel(Oid tableOid, Oid indexOid, int options) rebuild_relation(OldHeap, indexOid, verbose); /* NB: rebuild_relation does table_close() on OldHeap */ + + pgstat_progress_end_command(); } /* @@ -928,6 +949,17 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose, */ if (OldIndex != NULL && !use_sort) { + const int ci_index[] = { + PROGRESS_CLUSTER_PHASE, + PROGRESS_CLUSTER_INDEX_RELID + }; + int64 ci_val[2]; + + /* Set phase and OIDOldIndex to columns */ + ci_val[0] = PROGRESS_CLUSTER_PHASE_INDEX_SCAN_HEAP; + ci_val[1] = OIDOldIndex; + pgstat_progress_update_multi_param(2, ci_index, ci_val); + tableScan = NULL; heapScan = NULL; indexScan = index_beginscan(OldHeap, OldIndex, SnapshotAny, 0, 0); @@ -935,9 +967,17 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose, } else { + /* In scan-and-sort mode and also VACUUM FULL, set phase */ + pgstat_progress_update_param(PROGRESS_CLUSTER_PHASE, + PROGRESS_CLUSTER_PHASE_SEQ_SCAN_HEAP); + tableScan = table_beginscan(OldHeap, SnapshotAny, 0, (ScanKey) NULL); heapScan = (HeapScanDesc) tableScan; indexScan = NULL; + + /* Set total heap blocks */ + pgstat_progress_update_param(PROGRESS_CLUSTER_TOTAL_HEAP_BLKS, + heapScan->rs_nblocks); } slot = table_slot_create(OldHeap, NULL); @@ -994,6 +1034,10 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose, break; buf = heapScan->rs_cbuf; + + /* In scan-and-sort mode and also VACUUM FULL, set heap blocks scanned */ + pgstat_progress_update_param(PROGRESS_CLUSTER_HEAP_BLKS_SCANNED, + heapScan->rs_cblock + 1); } LockBuffer(buf, BUFFER_LOCK_SHARE); @@ -1064,12 +1108,31 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose, num_tuples += 1; if (tuplesort != NULL) + { tuplesort_putheaptuple(tuplesort, tuple); + + /* In scan-and-sort mode, report increase in number of tuples scanned */ + pgstat_progress_update_param(PROGRESS_CLUSTER_HEAP_TUPLES_SCANNED, + num_tuples); + } else + { + const int ct_index[] = { + PROGRESS_CLUSTER_HEAP_TUPLES_SCANNED, + PROGRESS_CLUSTER_HEAP_TUPLES_WRITTEN + }; + int64 ct_val[2]; + reform_and_rewrite_tuple(tuple, oldTupDesc, newTupDesc, values, isnull, rwstate); + + /* In indexscan mode and also VACUUM FULL, report increase in number of tuples scanned and written */ + ct_val[0] = num_tuples; + ct_val[1] = num_tuples; + pgstat_progress_update_multi_param(2, ct_index, ct_val); + } } if (indexScan != NULL) @@ -1085,8 +1148,17 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose, */ if (tuplesort != NULL) { + double n_tuples = 0; + /* Report that we are now sorting tuples */ + pgstat_progress_update_param(PROGRESS_CLUSTER_PHASE, + PROGRESS_CLUSTER_PHASE_SORT_TUPLES); + tuplesort_performsort(tuplesort); + /* Report that we are now writing new heap */ + pgstat_progress_update_param(PROGRESS_CLUSTER_PHASE, + PROGRESS_CLUSTER_PHASE_WRITE_NEW_HEAP); + for (;;) { HeapTuple tuple; @@ -1097,10 +1169,14 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose, if (tuple == NULL) break; + n_tuples += 1; reform_and_rewrite_tuple(tuple, oldTupDesc, newTupDesc, values, isnull, rwstate); + /* Report n_tuples */ + pgstat_progress_update_param(PROGRESS_CLUSTER_HEAP_TUPLES_WRITTEN, + n_tuples); } tuplesort_end(tuplesort); @@ -1539,6 +1615,10 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap, int reindex_flags; int i; + /* Report that we are now swapping relation files */ + pgstat_progress_update_param(PROGRESS_CLUSTER_PHASE, + PROGRESS_CLUSTER_PHASE_SWAP_REL_FILES); + /* Zero out possible results from swapped_relation_files */ memset(mapped_tables, 0, sizeof(mapped_tables)); @@ -1586,8 +1666,16 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap, else if (newrelpersistence == RELPERSISTENCE_PERMANENT) reindex_flags |= REINDEX_REL_FORCE_INDEXES_PERMANENT; + /* Report that we are now reindexing relations */ + pgstat_progress_update_param(PROGRESS_CLUSTER_PHASE, + PROGRESS_CLUSTER_PHASE_REBUILD_INDEX); + reindex_relation(OIDOldHeap, reindex_flags, 0); + /* Report that we are now doing clean up */ + pgstat_progress_update_param(PROGRESS_CLUSTER_PHASE, + PROGRESS_CLUSTER_PHASE_FINAL_CLEANUP); + /* * If the relation being rebuild is pg_class, swap_relation_files() * couldn't update pg_class's own pg_class entry (check comments in diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c index da1d685c081..90a817a25c5 100644 --- a/src/backend/utils/adt/pgstatfuncs.c +++ b/src/backend/utils/adt/pgstatfuncs.c @@ -468,6 +468,8 @@ pg_stat_get_progress_info(PG_FUNCTION_ARGS) /* Translate command name into command type code. */ if (pg_strcasecmp(cmd, "VACUUM") == 0) cmdtype = PROGRESS_COMMAND_VACUUM; + else if (pg_strcasecmp(cmd, "CLUSTER") == 0) + cmdtype = PROGRESS_COMMAND_CLUSTER; else ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index d4dfe237c99..c1e1d601ec5 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 201903221 +#define CATALOG_VERSION_NO 201903251 #endif diff --git a/src/include/commands/progress.h b/src/include/commands/progress.h index 9858b36a383..04542d9e923 100644 --- a/src/include/commands/progress.h +++ b/src/include/commands/progress.h @@ -34,4 +34,27 @@ #define PROGRESS_VACUUM_PHASE_TRUNCATE 5 #define PROGRESS_VACUUM_PHASE_FINAL_CLEANUP 6 +/* Progress parameters for cluster */ +#define PROGRESS_CLUSTER_COMMAND 0 +#define PROGRESS_CLUSTER_PHASE 1 +#define PROGRESS_CLUSTER_INDEX_RELID 2 +#define PROGRESS_CLUSTER_HEAP_TUPLES_SCANNED 3 +#define PROGRESS_CLUSTER_HEAP_TUPLES_WRITTEN 4 +#define PROGRESS_CLUSTER_TOTAL_HEAP_BLKS 5 +#define PROGRESS_CLUSTER_HEAP_BLKS_SCANNED 6 +#define PROGRESS_CLUSTER_INDEX_REBUILD_COUNT 7 + +/* Phases of cluster (as dvertised 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 +#define PROGRESS_CLUSTER_PHASE_WRITE_NEW_HEAP 4 +#define PROGRESS_CLUSTER_PHASE_SWAP_REL_FILES 5 +#define PROGRESS_CLUSTER_PHASE_REBUILD_INDEX 6 +#define PROGRESS_CLUSTER_PHASE_FINAL_CLEANUP 7 + +/* Commands of PROGRESS_CLUSTER */ +#define PROGRESS_CLUSTER_COMMAND_CLUSTER 1 +#define PROGRESS_CLUSTER_COMMAND_VACUUM_FULL 2 + #endif diff --git a/src/include/pgstat.h b/src/include/pgstat.h index ea6cc8b560f..c080fa6388f 100644 --- a/src/include/pgstat.h +++ b/src/include/pgstat.h @@ -950,7 +950,8 @@ typedef enum typedef enum ProgressCommandType { PROGRESS_COMMAND_INVALID, - PROGRESS_COMMAND_VACUUM + PROGRESS_COMMAND_VACUUM, + PROGRESS_COMMAND_CLUSTER } ProgressCommandType; #define PGSTAT_NUM_PROGRESS_PARAM 10 diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out index 8c33cd999d6..d5f309fbfbe 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -1830,6 +1830,34 @@ pg_stat_database_conflicts| SELECT d.oid AS datid, pg_stat_get_db_conflict_bufferpin(d.oid) AS confl_bufferpin, pg_stat_get_db_conflict_startup_deadlock(d.oid) AS confl_deadlock FROM pg_database d; +pg_stat_progress_cluster| SELECT s.pid, + s.datid, + d.datname, + s.relid, + CASE s.param1 + WHEN 1 THEN 'CLUSTER'::text + WHEN 2 THEN 'VACUUM FULL'::text + ELSE NULL::text + END AS command, + CASE s.param2 + WHEN 0 THEN 'initializing'::text + WHEN 1 THEN 'seq scanning heap'::text + WHEN 2 THEN 'index scanning heap'::text + WHEN 3 THEN 'sorting tuples'::text + WHEN 4 THEN 'writing new heap'::text + WHEN 5 THEN 'swapping relation files'::text + WHEN 6 THEN 'rebuilding index'::text + WHEN 7 THEN 'performing final cleanup'::text + ELSE NULL::text + END AS phase, + s.param3 AS cluster_index_relid, + s.param4 AS heap_tuples_scanned, + s.param5 AS heap_tuples_written, + s.param6 AS heap_blks_total, + s.param7 AS heap_blks_scanned, + s.param8 AS index_rebuild_count + FROM (pg_stat_get_progress_info('CLUSTER'::text) s(pid, datid, relid, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) + LEFT JOIN pg_database d ON ((s.datid = d.oid))); pg_stat_progress_vacuum| SELECT s.pid, s.datid, d.datname, |