Commit ecd222e7 authored by Fujii Masao's avatar Fujii Masao

Support VERBOSE option in REINDEX command.

When this option is specified, a progress report is printed as each index
is reindexed.

Per discussion, we agreed on the following syntax for the extensibility of
the options.

    REINDEX (flexible options) { INDEX | ... } name

Sawada Masahiko.
Reviewed by Robert Haas, Fabrízio Mello, Alvaro Herrera, Kyotaro Horiguchi,
Jim Nasby and me.

Discussion: CAD21AoA0pK3YcOZAFzMae+2fcc3oGp5zoRggDyMNg5zoaWDhdQ@mail.gmail.com
parent 4b8f797f
...@@ -21,7 +21,7 @@ PostgreSQL documentation ...@@ -21,7 +21,7 @@ PostgreSQL documentation
<refsynopsisdiv> <refsynopsisdiv>
<synopsis> <synopsis>
REINDEX { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable> REINDEX [ ( { VERBOSE } [, ...] ) ] { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable>
</synopsis> </synopsis>
</refsynopsisdiv> </refsynopsisdiv>
...@@ -150,6 +150,15 @@ REINDEX { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } <replaceable class="PARAM ...@@ -150,6 +150,15 @@ REINDEX { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } <replaceable class="PARAM
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><literal>VERBOSE</literal></term>
<listitem>
<para>
Prints a progress report as each index is reindexed.
</para>
</listitem>
</varlistentry>
</variablelist> </variablelist>
</refsect1> </refsect1>
......
...@@ -63,6 +63,7 @@ ...@@ -63,6 +63,7 @@
#include "utils/inval.h" #include "utils/inval.h"
#include "utils/lsyscache.h" #include "utils/lsyscache.h"
#include "utils/memutils.h" #include "utils/memutils.h"
#include "utils/pg_rusage.h"
#include "utils/syscache.h" #include "utils/syscache.h"
#include "utils/tuplesort.h" #include "utils/tuplesort.h"
#include "utils/snapmgr.h" #include "utils/snapmgr.h"
...@@ -3184,13 +3185,17 @@ IndexGetRelation(Oid indexId, bool missing_ok) ...@@ -3184,13 +3185,17 @@ IndexGetRelation(Oid indexId, bool missing_ok)
* reindex_index - This routine is used to recreate a single index * reindex_index - This routine is used to recreate a single index
*/ */
void void
reindex_index(Oid indexId, bool skip_constraint_checks, char persistence) reindex_index(Oid indexId, bool skip_constraint_checks, char persistence,
int options)
{ {
Relation iRel, Relation iRel,
heapRelation; heapRelation;
Oid heapId; Oid heapId;
IndexInfo *indexInfo; IndexInfo *indexInfo;
volatile bool skipped_constraint = false; volatile bool skipped_constraint = false;
PGRUsage ru0;
pg_rusage_init(&ru0);
/* /*
* Open and lock the parent heap relation. ShareLock is sufficient since * Open and lock the parent heap relation. ShareLock is sufficient since
...@@ -3334,6 +3339,14 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence) ...@@ -3334,6 +3339,14 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence)
heap_close(pg_index, RowExclusiveLock); heap_close(pg_index, RowExclusiveLock);
} }
/* Log what we did */
if (options & REINDEXOPT_VERBOSE)
ereport(INFO,
(errmsg("index \"%s\" was reindexed",
get_rel_name(indexId)),
errdetail("%s.",
pg_rusage_show(&ru0))));
/* Close rels, but keep locks */ /* Close rels, but keep locks */
index_close(iRel, NoLock); index_close(iRel, NoLock);
heap_close(heapRelation, NoLock); heap_close(heapRelation, NoLock);
...@@ -3375,7 +3388,7 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence) ...@@ -3375,7 +3388,7 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence)
* index rebuild. * index rebuild.
*/ */
bool bool
reindex_relation(Oid relid, int flags) reindex_relation(Oid relid, int flags, int options)
{ {
Relation rel; Relation rel;
Oid toast_relid; Oid toast_relid;
...@@ -3466,7 +3479,7 @@ reindex_relation(Oid relid, int flags) ...@@ -3466,7 +3479,7 @@ reindex_relation(Oid relid, int flags)
RelationSetIndexList(rel, doneIndexes, InvalidOid); RelationSetIndexList(rel, doneIndexes, InvalidOid);
reindex_index(indexOid, !(flags & REINDEX_REL_CHECK_CONSTRAINTS), reindex_index(indexOid, !(flags & REINDEX_REL_CHECK_CONSTRAINTS),
persistence); persistence, options);
CommandCounterIncrement(); CommandCounterIncrement();
...@@ -3501,7 +3514,7 @@ reindex_relation(Oid relid, int flags) ...@@ -3501,7 +3514,7 @@ reindex_relation(Oid relid, int flags)
* still hold the lock on the master table. * still hold the lock on the master table.
*/ */
if ((flags & REINDEX_REL_PROCESS_TOAST) && OidIsValid(toast_relid)) if ((flags & REINDEX_REL_PROCESS_TOAST) && OidIsValid(toast_relid))
result |= reindex_relation(toast_relid, flags); result |= reindex_relation(toast_relid, flags, options);
return result; return result;
} }
......
...@@ -1532,7 +1532,7 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap, ...@@ -1532,7 +1532,7 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap,
else if (newrelpersistence == RELPERSISTENCE_PERMANENT) else if (newrelpersistence == RELPERSISTENCE_PERMANENT)
reindex_flags |= REINDEX_REL_FORCE_INDEXES_PERMANENT; reindex_flags |= REINDEX_REL_FORCE_INDEXES_PERMANENT;
reindex_relation(OIDOldHeap, reindex_flags); reindex_relation(OIDOldHeap, reindex_flags, 0);
/* /*
* If the relation being rebuild is pg_class, swap_relation_files() * If the relation being rebuild is pg_class, swap_relation_files()
......
...@@ -1681,7 +1681,7 @@ ChooseIndexColumnNames(List *indexElems) ...@@ -1681,7 +1681,7 @@ ChooseIndexColumnNames(List *indexElems)
* Recreate a specific index. * Recreate a specific index.
*/ */
Oid Oid
ReindexIndex(RangeVar *indexRelation) ReindexIndex(RangeVar *indexRelation, int options)
{ {
Oid indOid; Oid indOid;
Oid heapOid = InvalidOid; Oid heapOid = InvalidOid;
...@@ -1706,7 +1706,7 @@ ReindexIndex(RangeVar *indexRelation) ...@@ -1706,7 +1706,7 @@ ReindexIndex(RangeVar *indexRelation)
persistence = irel->rd_rel->relpersistence; persistence = irel->rd_rel->relpersistence;
index_close(irel, NoLock); index_close(irel, NoLock);
reindex_index(indOid, false, persistence); reindex_index(indOid, false, persistence, options);
return indOid; return indOid;
} }
...@@ -1775,7 +1775,7 @@ RangeVarCallbackForReindexIndex(const RangeVar *relation, ...@@ -1775,7 +1775,7 @@ RangeVarCallbackForReindexIndex(const RangeVar *relation,
* Recreate all indexes of a table (and of its toast table, if any) * Recreate all indexes of a table (and of its toast table, if any)
*/ */
Oid Oid
ReindexTable(RangeVar *relation) ReindexTable(RangeVar *relation, int options)
{ {
Oid heapOid; Oid heapOid;
...@@ -1785,7 +1785,8 @@ ReindexTable(RangeVar *relation) ...@@ -1785,7 +1785,8 @@ ReindexTable(RangeVar *relation)
if (!reindex_relation(heapOid, if (!reindex_relation(heapOid,
REINDEX_REL_PROCESS_TOAST | REINDEX_REL_PROCESS_TOAST |
REINDEX_REL_CHECK_CONSTRAINTS)) REINDEX_REL_CHECK_CONSTRAINTS,
options))
ereport(NOTICE, ereport(NOTICE,
(errmsg("table \"%s\" has no indexes", (errmsg("table \"%s\" has no indexes",
relation->relname))); relation->relname)));
...@@ -1802,7 +1803,8 @@ ReindexTable(RangeVar *relation) ...@@ -1802,7 +1803,8 @@ ReindexTable(RangeVar *relation)
* That means this must not be called within a user transaction block! * That means this must not be called within a user transaction block!
*/ */
void void
ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind) ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind,
int options)
{ {
Oid objectOid; Oid objectOid;
Relation relationRelation; Relation relationRelation;
...@@ -1938,11 +1940,14 @@ ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind) ...@@ -1938,11 +1940,14 @@ ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind)
PushActiveSnapshot(GetTransactionSnapshot()); PushActiveSnapshot(GetTransactionSnapshot());
if (reindex_relation(relid, if (reindex_relation(relid,
REINDEX_REL_PROCESS_TOAST | REINDEX_REL_PROCESS_TOAST |
REINDEX_REL_CHECK_CONSTRAINTS)) REINDEX_REL_CHECK_CONSTRAINTS,
ereport(DEBUG1, options))
(errmsg("table \"%s.%s\" was reindexed",
get_namespace_name(get_rel_namespace(relid)), if (options & REINDEXOPT_VERBOSE)
get_rel_name(relid)))); ereport(INFO,
(errmsg("table \"%s.%s\" was reindexed",
get_namespace_name(get_rel_namespace(relid)),
get_rel_name(relid))));
PopActiveSnapshot(); PopActiveSnapshot();
CommitTransactionCommand(); CommitTransactionCommand();
} }
......
...@@ -1234,7 +1234,7 @@ ExecuteTruncate(TruncateStmt *stmt) ...@@ -1234,7 +1234,7 @@ ExecuteTruncate(TruncateStmt *stmt)
/* /*
* Reconstruct the indexes to match, and we're done. * Reconstruct the indexes to match, and we're done.
*/ */
reindex_relation(heap_relid, REINDEX_REL_PROCESS_TOAST); reindex_relation(heap_relid, REINDEX_REL_PROCESS_TOAST, 0);
} }
pgstat_count_truncate(rel); pgstat_count_truncate(rel);
......
...@@ -3856,6 +3856,7 @@ _copyReindexStmt(const ReindexStmt *from) ...@@ -3856,6 +3856,7 @@ _copyReindexStmt(const ReindexStmt *from)
COPY_SCALAR_FIELD(kind); COPY_SCALAR_FIELD(kind);
COPY_NODE_FIELD(relation); COPY_NODE_FIELD(relation);
COPY_STRING_FIELD(name); COPY_STRING_FIELD(name);
COPY_SCALAR_FIELD(options);
return newnode; return newnode;
} }
......
...@@ -1935,6 +1935,7 @@ _equalReindexStmt(const ReindexStmt *a, const ReindexStmt *b) ...@@ -1935,6 +1935,7 @@ _equalReindexStmt(const ReindexStmt *a, const ReindexStmt *b)
COMPARE_SCALAR_FIELD(kind); COMPARE_SCALAR_FIELD(kind);
COMPARE_NODE_FIELD(relation); COMPARE_NODE_FIELD(relation);
COMPARE_STRING_FIELD(name); COMPARE_STRING_FIELD(name);
COMPARE_SCALAR_FIELD(options);
return true; return true;
} }
......
...@@ -463,6 +463,10 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); ...@@ -463,6 +463,10 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <node> explain_option_arg %type <node> explain_option_arg
%type <defelt> explain_option_elem %type <defelt> explain_option_elem
%type <list> explain_option_list %type <list> explain_option_list
%type <ival> reindex_target_type reindex_target_multitable
%type <ival> reindex_option_list reindex_option_elem
%type <node> copy_generic_opt_arg copy_generic_opt_arg_list_item %type <node> copy_generic_opt_arg copy_generic_opt_arg_list_item
%type <defelt> copy_generic_opt_elem %type <defelt> copy_generic_opt_elem
%type <list> copy_generic_opt_list copy_generic_opt_arg_list %type <list> copy_generic_opt_list copy_generic_opt_arg_list
...@@ -7387,52 +7391,63 @@ DropTransformStmt: DROP TRANSFORM opt_if_exists FOR Typename LANGUAGE name opt_d ...@@ -7387,52 +7391,63 @@ DropTransformStmt: DROP TRANSFORM opt_if_exists FOR Typename LANGUAGE name opt_d
* *
* QUERY: * QUERY:
* *
* REINDEX type <name> * REINDEX [ (options) ] type <name>
*****************************************************************************/ *****************************************************************************/
ReindexStmt: ReindexStmt:
REINDEX INDEX qualified_name REINDEX reindex_target_type qualified_name
{ {
ReindexStmt *n = makeNode(ReindexStmt); ReindexStmt *n = makeNode(ReindexStmt);
n->kind = REINDEX_OBJECT_INDEX; n->kind = $2;
n->relation = $3; n->relation = $3;
n->name = NULL; n->name = NULL;
n->options = 0;
$$ = (Node *)n; $$ = (Node *)n;
} }
| REINDEX TABLE qualified_name | REINDEX reindex_target_multitable name
{ {
ReindexStmt *n = makeNode(ReindexStmt); ReindexStmt *n = makeNode(ReindexStmt);
n->kind = REINDEX_OBJECT_TABLE; n->kind = $2;
n->relation = $3;
n->name = NULL;
$$ = (Node *)n;
}
| REINDEX SCHEMA name
{
ReindexStmt *n = makeNode(ReindexStmt);
n->kind = REINDEX_OBJECT_SCHEMA;
n->name = $3; n->name = $3;
n->relation = NULL; n->relation = NULL;
n->options = 0;
$$ = (Node *)n; $$ = (Node *)n;
} }
| REINDEX SYSTEM_P name | REINDEX '(' reindex_option_list ')' reindex_target_type qualified_name
{ {
ReindexStmt *n = makeNode(ReindexStmt); ReindexStmt *n = makeNode(ReindexStmt);
n->kind = REINDEX_OBJECT_SYSTEM; n->kind = $5;
n->name = $3; n->relation = $6;
n->relation = NULL; n->name = NULL;
n->options = $3;
$$ = (Node *)n; $$ = (Node *)n;
} }
| REINDEX DATABASE name | REINDEX '(' reindex_option_list ')' reindex_target_multitable name
{ {
ReindexStmt *n = makeNode(ReindexStmt); ReindexStmt *n = makeNode(ReindexStmt);
n->kind = REINDEX_OBJECT_DATABASE; n->kind = $5;
n->name = $3; n->name = $6;
n->relation = NULL; n->relation = NULL;
n->options = $3;
$$ = (Node *)n; $$ = (Node *)n;
} }
; ;
reindex_target_type:
INDEX { $$ = REINDEX_OBJECT_INDEX; }
| TABLE { $$ = REINDEX_OBJECT_TABLE; }
;
reindex_target_multitable:
SCHEMA { $$ = REINDEX_OBJECT_SCHEMA; }
| SYSTEM_P { $$ = REINDEX_OBJECT_SYSTEM; }
| DATABASE { $$ = REINDEX_OBJECT_DATABASE; }
;
reindex_option_list:
reindex_option_elem { $$ = $1; }
| reindex_option_list ',' reindex_option_elem { $$ = $1 | $3; }
;
reindex_option_elem:
VERBOSE { $$ = REINDEXOPT_VERBOSE; }
;
/***************************************************************************** /*****************************************************************************
* *
......
...@@ -762,10 +762,10 @@ standard_ProcessUtility(Node *parsetree, ...@@ -762,10 +762,10 @@ standard_ProcessUtility(Node *parsetree,
switch (stmt->kind) switch (stmt->kind)
{ {
case REINDEX_OBJECT_INDEX: case REINDEX_OBJECT_INDEX:
ReindexIndex(stmt->relation); ReindexIndex(stmt->relation, stmt->options);
break; break;
case REINDEX_OBJECT_TABLE: case REINDEX_OBJECT_TABLE:
ReindexTable(stmt->relation); ReindexTable(stmt->relation, stmt->options);
break; break;
case REINDEX_OBJECT_SCHEMA: case REINDEX_OBJECT_SCHEMA:
case REINDEX_OBJECT_SYSTEM: case REINDEX_OBJECT_SYSTEM:
...@@ -781,7 +781,7 @@ standard_ProcessUtility(Node *parsetree, ...@@ -781,7 +781,7 @@ standard_ProcessUtility(Node *parsetree,
(stmt->kind == REINDEX_OBJECT_SCHEMA) ? "REINDEX SCHEMA" : (stmt->kind == REINDEX_OBJECT_SCHEMA) ? "REINDEX SCHEMA" :
(stmt->kind == REINDEX_OBJECT_SYSTEM) ? "REINDEX SYSTEM" : (stmt->kind == REINDEX_OBJECT_SYSTEM) ? "REINDEX SYSTEM" :
"REINDEX DATABASE"); "REINDEX DATABASE");
ReindexMultipleTables(stmt->name, stmt->kind); ReindexMultipleTables(stmt->name, stmt->kind, stmt->options);
break; break;
default: default:
elog(ERROR, "unrecognized object type: %d", elog(ERROR, "unrecognized object type: %d",
......
...@@ -115,7 +115,7 @@ extern void validate_index(Oid heapId, Oid indexId, Snapshot snapshot); ...@@ -115,7 +115,7 @@ extern void validate_index(Oid heapId, Oid indexId, Snapshot snapshot);
extern void index_set_state_flags(Oid indexId, IndexStateFlagsAction action); extern void index_set_state_flags(Oid indexId, IndexStateFlagsAction action);
extern void reindex_index(Oid indexId, bool skip_constraint_checks, extern void reindex_index(Oid indexId, bool skip_constraint_checks,
char relpersistence); char relpersistence, int options);
/* Flag bits for reindex_relation(): */ /* Flag bits for reindex_relation(): */
#define REINDEX_REL_PROCESS_TOAST 0x01 #define REINDEX_REL_PROCESS_TOAST 0x01
...@@ -124,7 +124,7 @@ extern void reindex_index(Oid indexId, bool skip_constraint_checks, ...@@ -124,7 +124,7 @@ extern void reindex_index(Oid indexId, bool skip_constraint_checks,
#define REINDEX_REL_FORCE_INDEXES_UNLOGGED 0x08 #define REINDEX_REL_FORCE_INDEXES_UNLOGGED 0x08
#define REINDEX_REL_FORCE_INDEXES_PERMANENT 0x10 #define REINDEX_REL_FORCE_INDEXES_PERMANENT 0x10
extern bool reindex_relation(Oid relid, int flags); extern bool reindex_relation(Oid relid, int flags, int options);
extern bool ReindexIsProcessingHeap(Oid heapOid); extern bool ReindexIsProcessingHeap(Oid heapOid);
extern bool ReindexIsProcessingIndex(Oid indexOid); extern bool ReindexIsProcessingIndex(Oid indexOid);
......
...@@ -29,9 +29,10 @@ extern ObjectAddress DefineIndex(Oid relationId, ...@@ -29,9 +29,10 @@ extern ObjectAddress DefineIndex(Oid relationId,
bool check_rights, bool check_rights,
bool skip_build, bool skip_build,
bool quiet); bool quiet);
extern Oid ReindexIndex(RangeVar *indexRelation); extern Oid ReindexIndex(RangeVar *indexRelation, int options);
extern Oid ReindexTable(RangeVar *relation); extern Oid ReindexTable(RangeVar *relation, int options);
extern void ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind); extern void ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind,
int options);
extern char *makeObjectName(const char *name1, const char *name2, extern char *makeObjectName(const char *name1, const char *name2,
const char *label); const char *label);
extern char *ChooseRelationName(const char *name1, const char *name2, extern char *ChooseRelationName(const char *name1, const char *name2,
......
...@@ -2782,6 +2782,10 @@ typedef struct ConstraintsSetStmt ...@@ -2782,6 +2782,10 @@ typedef struct ConstraintsSetStmt
* REINDEX Statement * REINDEX Statement
* ---------------------- * ----------------------
*/ */
/* Reindex options */
#define REINDEXOPT_VERBOSE 1 << 0 /* print progress info */
typedef enum ReindexObjectType typedef enum ReindexObjectType
{ {
REINDEX_OBJECT_INDEX, /* index */ REINDEX_OBJECT_INDEX, /* index */
...@@ -2797,6 +2801,7 @@ typedef struct ReindexStmt ...@@ -2797,6 +2801,7 @@ typedef struct ReindexStmt
ReindexObjectType kind; /* REINDEX_OBJECT_INDEX, REINDEX_OBJECT_TABLE, etc. */ ReindexObjectType kind; /* REINDEX_OBJECT_INDEX, REINDEX_OBJECT_TABLE, etc. */
RangeVar *relation; /* Table or index to reindex */ RangeVar *relation; /* Table or index to reindex */
const char *name; /* name of database to reindex */ const char *name; /* name of database to reindex */
int options; /* Reindex options flags */
} ReindexStmt; } ReindexStmt;
/* ---------------------- /* ----------------------
......
...@@ -2831,6 +2831,14 @@ explain (costs off) ...@@ -2831,6 +2831,14 @@ explain (costs off)
Index Cond: ((thousand = 1) AND (tenthous = 1001)) Index Cond: ((thousand = 1) AND (tenthous = 1001))
(2 rows) (2 rows)
--
-- REINDEX (VERBOSE)
--
CREATE TABLE reindex_verbose(id integer primary key);
\set VERBOSITY terse
REINDEX (VERBOSE) TABLE reindex_verbose;
INFO: index "reindex_verbose_pkey" was reindexed
DROP TABLE reindex_verbose;
-- --
-- REINDEX SCHEMA -- REINDEX SCHEMA
-- --
......
...@@ -965,6 +965,14 @@ RESET enable_indexscan; ...@@ -965,6 +965,14 @@ RESET enable_indexscan;
explain (costs off) explain (costs off)
select * from tenk1 where (thousand, tenthous) in ((1,1001), (null,null)); select * from tenk1 where (thousand, tenthous) in ((1,1001), (null,null));
--
-- REINDEX (VERBOSE)
--
CREATE TABLE reindex_verbose(id integer primary key);
\set VERBOSITY terse
REINDEX (VERBOSE) TABLE reindex_verbose;
DROP TABLE reindex_verbose;
-- --
-- REINDEX SCHEMA -- REINDEX SCHEMA
-- --
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment