Reduce the size of memory allocations by lazy vacuum when processing a small
authorAlvaro Herrera
Mon, 24 Sep 2007 03:52:55 +0000 (03:52 +0000)
committerAlvaro Herrera
Mon, 24 Sep 2007 03:52:55 +0000 (03:52 +0000)
table, by allocating just enough for a hardcoded number of dead tuples per
page.  The current estimate is 200 dead tuples per page.

Per reports from Jeff Amiel, Erik Jones and Marko Kreen, and subsequent
discussion.
CVS: ----------------------------------------------------------------------
CVS: Enter Log.  Lines beginning with `CVS:' are removed automatically
CVS:
CVS: Committing in .
CVS:
CVS: Modified Files:
CVS:  commands/vacuumlazy.c
CVS: ----------------------------------------------------------------------

src/backend/commands/vacuumlazy.c

index df8951ee1e746d8f2c13646a73deb8441b7b69f7..91b2d755f14fd3d2d1471d41b481d5c6b33eb04c 100644 (file)
  * on the number of tuples and pages we will keep track of at once.
  *
  * We are willing to use at most maintenance_work_mem memory space to keep
- * track of dead tuples.  We initially allocate an array of TIDs of that size.
- * If the array threatens to overflow, we suspend the heap scan phase and
- * perform a pass of index cleanup and page compaction, then resume the heap
- * scan with an empty TID array.
+ * track of dead tuples.  We initially allocate an array of TIDs of that size,
+ * with an upper limit that depends on table size (this limit ensures we don't
+ * allocate a huge area uselessly for vacuuming small tables).  If the array
+ * threatens to overflow, we suspend the heap scan phase and perform a pass of
+ * index cleanup and page compaction, then resume the heap scan with an empty
+ * TID array.
  *
  * We can limit the storage for page free space to MaxFSMPages entries,
  * since that's the most the free space map will be willing to remember
@@ -36,7 +38,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.99 2007/09/24 03:12:23 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.100 2007/09/24 03:52:55 alvherre Exp $
  *
  *-------------------------------------------------------------------------
  */
 #define REL_TRUNCATE_MINIMUM   1000
 #define REL_TRUNCATE_FRACTION  16
 
+/*
+ * Guesstimation of number of dead tuples per page.  This is used to
+ * provide an upper limit to memory allocated when vacuuming small
+ * tables.
+ */
+#define LAZY_ALLOC_TUPLES      200
 
 typedef struct LVRelStats
 {
@@ -1001,6 +1009,11 @@ lazy_space_alloc(LVRelStats *vacrelstats, BlockNumber relblocks)
        maxtuples = (maintenance_work_mem * 1024L) / sizeof(ItemPointerData);
        maxtuples = Min(maxtuples, INT_MAX);
        maxtuples = Min(maxtuples, MaxAllocSize / sizeof(ItemPointerData));
+
+       /* curious coding here to ensure the multiplication can't overflow */
+       if ((BlockNumber) (maxtuples / LAZY_ALLOC_TUPLES) > relblocks)
+           maxtuples = relblocks * LAZY_ALLOC_TUPLES;
+
        /* stay sane if small maintenance_work_mem */
        maxtuples = Max(maxtuples, MaxHeapTuplesPerPage);
    }