4545#include "utils/inval.h"
4646#include "utils/lsyscache.h"
4747#include "utils/memutils.h"
48+ #include "utils/pg_rusage.h"
4849#include "utils/relcache.h"
4950#include "utils/relmapper.h"
5051#include "utils/snapmgr.h"
@@ -66,9 +67,9 @@ typedef struct
6667
6768
6869static void rebuild_relation (Relation OldHeap ,Oid indexOid ,
69- int freeze_min_age ,int freeze_table_age );
70+ int freeze_min_age ,int freeze_table_age , bool verbose );
7071static void copy_heap_data (Oid OIDNewHeap ,Oid OIDOldHeap ,Oid OIDOldIndex ,
71- int freeze_min_age ,int freeze_table_age ,
72+ int freeze_min_age ,int freeze_table_age ,bool verbose ,
7273bool * pSwapToastByContent ,TransactionId * pFreezeXid );
7374static List * get_tables_to_cluster (MemoryContext cluster_context );
7475static void reform_and_rewrite_tuple (HeapTuple tuple ,
@@ -383,20 +384,9 @@ cluster_rel(Oid tableOid, Oid indexOid, bool recheck, bool verbose,
383384if (OidIsValid (indexOid ))
384385check_index_is_clusterable (OldHeap ,indexOid ,recheck ,AccessExclusiveLock );
385386
386- /* Log what we're doing (this could use more effort) */
387- if (OidIsValid (indexOid ))
388- ereport (verbose ?INFO :DEBUG2 ,
389- (errmsg ("clustering \"%s.%s\"" ,
390- get_namespace_name (RelationGetNamespace (OldHeap )),
391- RelationGetRelationName (OldHeap ))));
392- else
393- ereport (verbose ?INFO :DEBUG2 ,
394- (errmsg ("vacuuming \"%s.%s\"" ,
395- get_namespace_name (RelationGetNamespace (OldHeap )),
396- RelationGetRelationName (OldHeap ))));
397-
398387/* rebuild_relation does all the dirty work */
399- rebuild_relation (OldHeap ,indexOid ,freeze_min_age ,freeze_table_age );
388+ rebuild_relation (OldHeap ,indexOid ,freeze_min_age ,freeze_table_age ,
389+ verbose );
400390
401391/* NB: rebuild_relation does heap_close() on OldHeap */
402392}
@@ -580,7 +570,7 @@ mark_index_clustered(Relation rel, Oid indexOid)
580570 */
581571static void
582572rebuild_relation (Relation OldHeap ,Oid indexOid ,
583- int freeze_min_age ,int freeze_table_age )
573+ int freeze_min_age ,int freeze_table_age , bool verbose )
584574{
585575Oid tableOid = RelationGetRelid (OldHeap );
586576Oid tableSpace = OldHeap -> rd_rel -> reltablespace ;
@@ -604,7 +594,7 @@ rebuild_relation(Relation OldHeap, Oid indexOid,
604594
605595/* Copy the heap data into the new table in the desired order */
606596copy_heap_data (OIDNewHeap ,tableOid ,indexOid ,
607- freeze_min_age ,freeze_table_age ,
597+ freeze_min_age ,freeze_table_age ,verbose ,
608598& swap_toast_by_content ,& frozenXid );
609599
610600/*
@@ -746,7 +736,7 @@ make_new_heap(Oid OIDOldHeap, Oid NewTableSpace)
746736 */
747737static void
748738copy_heap_data (Oid OIDNewHeap ,Oid OIDOldHeap ,Oid OIDOldIndex ,
749- int freeze_min_age ,int freeze_table_age ,
739+ int freeze_min_age ,int freeze_table_age ,bool verbose ,
750740bool * pSwapToastByContent ,TransactionId * pFreezeXid )
751741{
752742Relation NewHeap ,
@@ -766,6 +756,13 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex,
766756RewriteState rwstate ;
767757bool use_sort ;
768758Tuplesortstate * tuplesort ;
759+ double num_tuples = 0 ,
760+ tups_vacuumed = 0 ,
761+ tups_recently_dead = 0 ;
762+ int elevel = verbose ?INFO :DEBUG2 ;
763+ PGRUsage ru0 ;
764+
765+ pg_rusage_init (& ru0 );
769766
770767/*
771768 * Open the relations we need.
@@ -887,6 +884,24 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex,
887884indexScan = NULL ;
888885}
889886
887+ /* Log what we're doing */
888+ if (indexScan != NULL )
889+ ereport (elevel ,
890+ (errmsg ("clustering \"%s.%s\" using index scan on \"%s\"" ,
891+ get_namespace_name (RelationGetNamespace (OldHeap )),
892+ RelationGetRelationName (OldHeap ),
893+ RelationGetRelationName (OldIndex ))));
894+ else if (tuplesort != NULL )
895+ ereport (elevel ,
896+ (errmsg ("clustering \"%s.%s\" using sequential scan and sort" ,
897+ get_namespace_name (RelationGetNamespace (OldHeap )),
898+ RelationGetRelationName (OldHeap ))));
899+ else
900+ ereport (elevel ,
901+ (errmsg ("vacuuming \"%s.%s\"" ,
902+ get_namespace_name (RelationGetNamespace (OldHeap )),
903+ RelationGetRelationName (OldHeap ))));
904+
890905/*
891906 * Scan through the OldHeap, either in OldIndex order or sequentially;
892907 * copy each tuple into the NewHeap, or transiently to the tuplesort
@@ -930,8 +945,10 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex,
930945/* Definitely dead */
931946isdead = true;
932947break ;
933- case HEAPTUPLE_LIVE :
934948case HEAPTUPLE_RECENTLY_DEAD :
949+ tups_recently_dead += 1 ;
950+ /* fall through */
951+ case HEAPTUPLE_LIVE :
935952/* Live or recently dead, must copy it */
936953isdead = false;
937954break ;
@@ -963,6 +980,7 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex,
963980elog (WARNING ,"concurrent delete in progress within table \"%s\"" ,
964981RelationGetRelationName (OldHeap ));
965982/* treat as recently dead */
983+ tups_recently_dead += 1 ;
966984isdead = false;
967985break ;
968986default :
@@ -975,11 +993,18 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex,
975993
976994if (isdead )
977995{
996+ tups_vacuumed += 1 ;
978997/* heap rewrite module still needs to see it... */
979- rewrite_heap_dead_tuple (rwstate ,tuple );
998+ if (rewrite_heap_dead_tuple (rwstate ,tuple ))
999+ {
1000+ /* A previous recently-dead tuple is now known dead */
1001+ tups_vacuumed += 1 ;
1002+ tups_recently_dead -= 1 ;
1003+ }
9801004continue ;
9811005}
9821006
1007+ num_tuples += 1 ;
9831008if (tuplesort != NULL )
9841009tuplesort_putheaptuple (tuplesort ,tuple );
9851010else
@@ -1031,6 +1056,17 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex,
10311056/* Reset rd_toastoid just to be tidy --- it shouldn't be looked at again */
10321057NewHeap -> rd_toastoid = InvalidOid ;
10331058
1059+ /* Log what we did */
1060+ ereport (elevel ,
1061+ (errmsg ("\"%s\": found %.0f removable, %.0f nonremovable row versions in %u pages" ,
1062+ RelationGetRelationName (OldHeap ),
1063+ tups_vacuumed ,num_tuples ,
1064+ RelationGetNumberOfBlocks (OldHeap )),
1065+ errdetail ("%.0f dead row versions cannot be removed yet.\n"
1066+ "%s." ,
1067+ tups_recently_dead ,
1068+ pg_rusage_show (& ru0 ))));
1069+
10341070/* Clean up */
10351071pfree (values );
10361072pfree (isnull );