Commit 9cc8c84e authored by Tom Lane's avatar Tom Lane

Improve logging in VACUUM FULL VERBOSE and CLUSTER VERBOSE.

This patch resurrects some of the information that could be logged by the
old, now-dead implementation of VACUUM FULL, in particular counts of live
and dead tuples and the time taken for the table rebuild proper.  There's
still no logging about the ensuing index rebuilds, though.

Itagaki Takahiro
parent 26a7b48e
...@@ -254,8 +254,6 @@ end_heap_rewrite(RewriteState state) ...@@ -254,8 +254,6 @@ end_heap_rewrite(RewriteState state)
/* /*
* Write any remaining tuples in the UnresolvedTups table. If we have any * Write any remaining tuples in the UnresolvedTups table. If we have any
* left, they should in fact be dead, but let's err on the safe side. * left, they should in fact be dead, but let's err on the safe side.
*
* XXX this really is a waste of code no?
*/ */
hash_seq_init(&seq_status, state->rs_unresolved_tups); hash_seq_init(&seq_status, state->rs_unresolved_tups);
...@@ -502,8 +500,12 @@ rewrite_heap_tuple(RewriteState state, ...@@ -502,8 +500,12 @@ rewrite_heap_tuple(RewriteState state,
* Register a dead tuple with an ongoing rewrite. Dead tuples are not * Register a dead tuple with an ongoing rewrite. Dead tuples are not
* copied to the new table, but we still make note of them so that we * copied to the new table, but we still make note of them so that we
* can release some resources earlier. * can release some resources earlier.
*
* Returns true if a tuple was removed from the unresolved_tups table.
* This indicates that that tuple, previously thought to be "recently dead",
* is now known really dead and won't be written to the output.
*/ */
void bool
rewrite_heap_dead_tuple(RewriteState state, HeapTuple old_tuple) rewrite_heap_dead_tuple(RewriteState state, HeapTuple old_tuple)
{ {
/* /*
...@@ -539,7 +541,10 @@ rewrite_heap_dead_tuple(RewriteState state, HeapTuple old_tuple) ...@@ -539,7 +541,10 @@ rewrite_heap_dead_tuple(RewriteState state, HeapTuple old_tuple)
hash_search(state->rs_unresolved_tups, &hashkey, hash_search(state->rs_unresolved_tups, &hashkey,
HASH_REMOVE, &found); HASH_REMOVE, &found);
Assert(found); Assert(found);
return true;
} }
return false;
} }
/* /*
......
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,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/relcache.h" #include "utils/relcache.h"
#include "utils/relmapper.h" #include "utils/relmapper.h"
#include "utils/snapmgr.h" #include "utils/snapmgr.h"
...@@ -66,9 +67,9 @@ typedef struct ...@@ -66,9 +67,9 @@ typedef struct
static void rebuild_relation(Relation OldHeap, Oid indexOid, static void rebuild_relation(Relation OldHeap, Oid indexOid,
int freeze_min_age, int freeze_table_age); int freeze_min_age, int freeze_table_age, bool verbose);
static void copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, static void copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex,
int freeze_min_age, int freeze_table_age, int freeze_min_age, int freeze_table_age, bool verbose,
bool *pSwapToastByContent, TransactionId *pFreezeXid); bool *pSwapToastByContent, TransactionId *pFreezeXid);
static List *get_tables_to_cluster(MemoryContext cluster_context); static List *get_tables_to_cluster(MemoryContext cluster_context);
static void reform_and_rewrite_tuple(HeapTuple tuple, static void reform_and_rewrite_tuple(HeapTuple tuple,
...@@ -383,20 +384,9 @@ cluster_rel(Oid tableOid, Oid indexOid, bool recheck, bool verbose, ...@@ -383,20 +384,9 @@ cluster_rel(Oid tableOid, Oid indexOid, bool recheck, bool verbose,
if (OidIsValid(indexOid)) if (OidIsValid(indexOid))
check_index_is_clusterable(OldHeap, indexOid, recheck, AccessExclusiveLock); check_index_is_clusterable(OldHeap, indexOid, recheck, AccessExclusiveLock);
/* Log what we're doing (this could use more effort) */
if (OidIsValid(indexOid))
ereport(verbose ? INFO : DEBUG2,
(errmsg("clustering \"%s.%s\"",
get_namespace_name(RelationGetNamespace(OldHeap)),
RelationGetRelationName(OldHeap))));
else
ereport(verbose ? INFO : DEBUG2,
(errmsg("vacuuming \"%s.%s\"",
get_namespace_name(RelationGetNamespace(OldHeap)),
RelationGetRelationName(OldHeap))));
/* rebuild_relation does all the dirty work */ /* rebuild_relation does all the dirty work */
rebuild_relation(OldHeap, indexOid, freeze_min_age, freeze_table_age); rebuild_relation(OldHeap, indexOid, freeze_min_age, freeze_table_age,
verbose);
/* NB: rebuild_relation does heap_close() on OldHeap */ /* NB: rebuild_relation does heap_close() on OldHeap */
} }
...@@ -580,7 +570,7 @@ mark_index_clustered(Relation rel, Oid indexOid) ...@@ -580,7 +570,7 @@ mark_index_clustered(Relation rel, Oid indexOid)
*/ */
static void static void
rebuild_relation(Relation OldHeap, Oid indexOid, rebuild_relation(Relation OldHeap, Oid indexOid,
int freeze_min_age, int freeze_table_age) int freeze_min_age, int freeze_table_age, bool verbose)
{ {
Oid tableOid = RelationGetRelid(OldHeap); Oid tableOid = RelationGetRelid(OldHeap);
Oid tableSpace = OldHeap->rd_rel->reltablespace; Oid tableSpace = OldHeap->rd_rel->reltablespace;
...@@ -604,7 +594,7 @@ rebuild_relation(Relation OldHeap, Oid indexOid, ...@@ -604,7 +594,7 @@ rebuild_relation(Relation OldHeap, Oid indexOid,
/* Copy the heap data into the new table in the desired order */ /* Copy the heap data into the new table in the desired order */
copy_heap_data(OIDNewHeap, tableOid, indexOid, copy_heap_data(OIDNewHeap, tableOid, indexOid,
freeze_min_age, freeze_table_age, freeze_min_age, freeze_table_age, verbose,
&swap_toast_by_content, &frozenXid); &swap_toast_by_content, &frozenXid);
/* /*
...@@ -746,7 +736,7 @@ make_new_heap(Oid OIDOldHeap, Oid NewTableSpace) ...@@ -746,7 +736,7 @@ make_new_heap(Oid OIDOldHeap, Oid NewTableSpace)
*/ */
static void static void
copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex,
int freeze_min_age, int freeze_table_age, int freeze_min_age, int freeze_table_age, bool verbose,
bool *pSwapToastByContent, TransactionId *pFreezeXid) bool *pSwapToastByContent, TransactionId *pFreezeXid)
{ {
Relation NewHeap, Relation NewHeap,
...@@ -766,6 +756,13 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, ...@@ -766,6 +756,13 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex,
RewriteState rwstate; RewriteState rwstate;
bool use_sort; bool use_sort;
Tuplesortstate *tuplesort; Tuplesortstate *tuplesort;
double num_tuples = 0,
tups_vacuumed = 0,
tups_recently_dead = 0;
int elevel = verbose ? INFO : DEBUG2;
PGRUsage ru0;
pg_rusage_init(&ru0);
/* /*
* Open the relations we need. * Open the relations we need.
...@@ -887,6 +884,24 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, ...@@ -887,6 +884,24 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex,
indexScan = NULL; indexScan = NULL;
} }
/* Log what we're doing */
if (indexScan != NULL)
ereport(elevel,
(errmsg("clustering \"%s.%s\" using index scan on \"%s\"",
get_namespace_name(RelationGetNamespace(OldHeap)),
RelationGetRelationName(OldHeap),
RelationGetRelationName(OldIndex))));
else if (tuplesort != NULL)
ereport(elevel,
(errmsg("clustering \"%s.%s\" using sequential scan and sort",
get_namespace_name(RelationGetNamespace(OldHeap)),
RelationGetRelationName(OldHeap))));
else
ereport(elevel,
(errmsg("vacuuming \"%s.%s\"",
get_namespace_name(RelationGetNamespace(OldHeap)),
RelationGetRelationName(OldHeap))));
/* /*
* Scan through the OldHeap, either in OldIndex order or sequentially; * Scan through the OldHeap, either in OldIndex order or sequentially;
* copy each tuple into the NewHeap, or transiently to the tuplesort * copy each tuple into the NewHeap, or transiently to the tuplesort
...@@ -930,8 +945,10 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, ...@@ -930,8 +945,10 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex,
/* Definitely dead */ /* Definitely dead */
isdead = true; isdead = true;
break; break;
case HEAPTUPLE_LIVE:
case HEAPTUPLE_RECENTLY_DEAD: case HEAPTUPLE_RECENTLY_DEAD:
tups_recently_dead += 1;
/* fall through */
case HEAPTUPLE_LIVE:
/* Live or recently dead, must copy it */ /* Live or recently dead, must copy it */
isdead = false; isdead = false;
break; break;
...@@ -963,6 +980,7 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, ...@@ -963,6 +980,7 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex,
elog(WARNING, "concurrent delete in progress within table \"%s\"", elog(WARNING, "concurrent delete in progress within table \"%s\"",
RelationGetRelationName(OldHeap)); RelationGetRelationName(OldHeap));
/* treat as recently dead */ /* treat as recently dead */
tups_recently_dead += 1;
isdead = false; isdead = false;
break; break;
default: default:
...@@ -975,11 +993,18 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, ...@@ -975,11 +993,18 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex,
if (isdead) if (isdead)
{ {
tups_vacuumed += 1;
/* heap rewrite module still needs to see it... */ /* heap rewrite module still needs to see it... */
rewrite_heap_dead_tuple(rwstate, tuple); if (rewrite_heap_dead_tuple(rwstate, tuple))
{
/* A previous recently-dead tuple is now known dead */
tups_vacuumed += 1;
tups_recently_dead -= 1;
}
continue; continue;
} }
num_tuples += 1;
if (tuplesort != NULL) if (tuplesort != NULL)
tuplesort_putheaptuple(tuplesort, tuple); tuplesort_putheaptuple(tuplesort, tuple);
else else
...@@ -1031,6 +1056,17 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, ...@@ -1031,6 +1056,17 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex,
/* Reset rd_toastoid just to be tidy --- it shouldn't be looked at again */ /* Reset rd_toastoid just to be tidy --- it shouldn't be looked at again */
NewHeap->rd_toastoid = InvalidOid; NewHeap->rd_toastoid = InvalidOid;
/* Log what we did */
ereport(elevel,
(errmsg("\"%s\": found %.0f removable, %.0f nonremovable row versions in %u pages",
RelationGetRelationName(OldHeap),
tups_vacuumed, num_tuples,
RelationGetNumberOfBlocks(OldHeap)),
errdetail("%.0f dead row versions cannot be removed yet.\n"
"%s.",
tups_recently_dead,
pg_rusage_show(&ru0))));
/* Clean up */ /* Clean up */
pfree(values); pfree(values);
pfree(isnull); pfree(isnull);
......
...@@ -25,6 +25,6 @@ extern RewriteState begin_heap_rewrite(Relation NewHeap, ...@@ -25,6 +25,6 @@ extern RewriteState begin_heap_rewrite(Relation NewHeap,
extern void end_heap_rewrite(RewriteState state); extern void end_heap_rewrite(RewriteState state);
extern void rewrite_heap_tuple(RewriteState state, HeapTuple oldTuple, extern void rewrite_heap_tuple(RewriteState state, HeapTuple oldTuple,
HeapTuple newTuple); HeapTuple newTuple);
extern void rewrite_heap_dead_tuple(RewriteState state, HeapTuple oldTuple); extern bool rewrite_heap_dead_tuple(RewriteState state, HeapTuple oldTuple);
#endif /* REWRITE_HEAP_H */ #endif /* REWRITE_HEAP_H */
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