Reduce memory consumption during VACUUM of large relations, by using
authorTom Lane
Mon, 10 Mar 2008 02:04:10 +0000 (02:04 +0000)
committerTom Lane
Mon, 10 Mar 2008 02:04:10 +0000 (02:04 +0000)
FSMPageData (6 bytes) instead of PageFreeSpaceInfo (8 or 16 bytes)
for the temporary array of page-free-space information.

Itagaki Takahiro

src/backend/commands/vacuum.c
src/backend/commands/vacuumlazy.c
src/backend/storage/freespace/freespace.c
src/include/storage/freespace.h

index 7e31ac452a7f42fd3cc9dcb2dab391aae3445d21..a073a1d68e5560fdac1605e487d03258786c8737 100644 (file)
@@ -13,7 +13,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.365 2008/02/20 14:31:35 alvherre Exp $
+ *   $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.366 2008/03/10 02:04:08 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -3461,7 +3461,7 @@ vac_update_fsm(Relation onerel, VacPageList fraged_pages,
    int         nPages = fraged_pages->num_pages;
    VacPage    *pagedesc = fraged_pages->pagedesc;
    Size        threshold;
-   PageFreeSpaceInfo *pageSpaces;
+   FSMPageData *pageSpaces;
    int         outPages;
    int         i;
 
@@ -3477,8 +3477,7 @@ vac_update_fsm(Relation onerel, VacPageList fraged_pages,
     */
    threshold = GetAvgFSMRequestSize(&onerel->rd_node);
 
-   pageSpaces = (PageFreeSpaceInfo *)
-       palloc(nPages * sizeof(PageFreeSpaceInfo));
+   pageSpaces = (FSMPageData *) palloc(nPages * sizeof(FSMPageData));
    outPages = 0;
 
    for (i = 0; i < nPages; i++)
@@ -3493,8 +3492,8 @@ vac_update_fsm(Relation onerel, VacPageList fraged_pages,
 
        if (pagedesc[i]->free >= threshold)
        {
-           pageSpaces[outPages].blkno = pagedesc[i]->blkno;
-           pageSpaces[outPages].avail = pagedesc[i]->free;
+           FSMPageSetPageNum(&pageSpaces[outPages], pagedesc[i]->blkno);
+           FSMPageSetSpace(&pageSpaces[outPages], pagedesc[i]->free);
            outPages++;
        }
    }
index 7adde03f4ac6819d518a8a357e08bb8bfcf39cb8..d524e52b55522b66a5ba84e6438c3622e0723943 100644 (file)
@@ -38,7 +38,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.103 2008/01/01 19:45:49 momjian Exp $
+ *   $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.104 2008/03/10 02:04:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -98,7 +98,7 @@ typedef struct LVRelStats
    bool        fs_is_heap;     /* are we using heap organization? */
    int         num_free_pages; /* current # of entries */
    int         max_free_pages; /* # slots allocated in array */
-   PageFreeSpaceInfo *free_pages;      /* array or heap of blkno/avail */
+   FSMPageData *free_pages;    /* array or heap of blkno/avail */
    BlockNumber tot_free_pages; /* total pages with >= threshold space */
    int         num_index_scans;
 } LVRelStats;
@@ -813,7 +813,7 @@ lazy_truncate_heap(Relation onerel, LVRelStats *vacrelstats)
 {
    BlockNumber old_rel_pages = vacrelstats->rel_pages;
    BlockNumber new_rel_pages;
-   PageFreeSpaceInfo *pageSpaces;
+   FSMPageData *pageSpaces;
    int         n;
    int         i,
                j;
@@ -881,7 +881,7 @@ lazy_truncate_heap(Relation onerel, LVRelStats *vacrelstats)
    j = 0;
    for (i = 0; i < n; i++)
    {
-       if (pageSpaces[i].blkno < new_rel_pages)
+       if (FSMPageGetPageNum(&pageSpaces[i]) < new_rel_pages)
        {
            pageSpaces[j] = pageSpaces[i];
            j++;
@@ -1028,7 +1028,7 @@ lazy_space_alloc(LVRelStats *vacrelstats, BlockNumber relblocks)
        palloc(maxtuples * sizeof(ItemPointerData));
 
    maxpages = MaxFSMPages;
-   maxpages = Min(maxpages, MaxAllocSize / sizeof(PageFreeSpaceInfo));
+   maxpages = Min(maxpages, MaxAllocSize / sizeof(FSMPageData));
    /* No need to allocate more pages than the relation has blocks */
    if (relblocks < (BlockNumber) maxpages)
        maxpages = (int) relblocks;
@@ -1036,8 +1036,8 @@ lazy_space_alloc(LVRelStats *vacrelstats, BlockNumber relblocks)
    vacrelstats->fs_is_heap = false;
    vacrelstats->num_free_pages = 0;
    vacrelstats->max_free_pages = maxpages;
-   vacrelstats->free_pages = (PageFreeSpaceInfo *)
-       palloc(maxpages * sizeof(PageFreeSpaceInfo));
+   vacrelstats->free_pages = (FSMPageData *)
+       palloc(maxpages * sizeof(FSMPageData));
    vacrelstats->tot_free_pages = 0;
 }
 
@@ -1068,7 +1068,7 @@ lazy_record_free_space(LVRelStats *vacrelstats,
                       BlockNumber page,
                       Size avail)
 {
-   PageFreeSpaceInfo *pageSpaces;
+   FSMPageData *pageSpaces;
    int         n;
 
    /*
@@ -1098,8 +1098,8 @@ lazy_record_free_space(LVRelStats *vacrelstats,
    /* If we haven't filled the array yet, just keep adding entries */
    if (vacrelstats->num_free_pages < n)
    {
-       pageSpaces[vacrelstats->num_free_pages].blkno = page;
-       pageSpaces[vacrelstats->num_free_pages].avail = avail;
+       FSMPageSetPageNum(&pageSpaces[vacrelstats->num_free_pages], page);
+       FSMPageSetSpace(&pageSpaces[vacrelstats->num_free_pages], avail);
        vacrelstats->num_free_pages++;
        return;
    }
@@ -1127,8 +1127,8 @@ lazy_record_free_space(LVRelStats *vacrelstats,
 
        while (--l >= 0)
        {
-           BlockNumber R = pageSpaces[l].blkno;
-           Size        K = pageSpaces[l].avail;
+           BlockNumber R = FSMPageGetPageNum(&pageSpaces[l]);
+           Size        K = FSMPageGetSpace(&pageSpaces[l]);
            int         i;      /* i is where the "hole" is */
 
            i = l;
@@ -1138,22 +1138,22 @@ lazy_record_free_space(LVRelStats *vacrelstats,
 
                if (j >= n)
                    break;
-               if (j + 1 < n && pageSpaces[j].avail > pageSpaces[j + 1].avail)
+               if (j + 1 < n && FSMPageGetSpace(&pageSpaces[j]) > FSMPageGetSpace(&pageSpaces[j + 1]))
                    j++;
-               if (K <= pageSpaces[j].avail)
+               if (K <= FSMPageGetSpace(&pageSpaces[j]))
                    break;
                pageSpaces[i] = pageSpaces[j];
                i = j;
            }
-           pageSpaces[i].blkno = R;
-           pageSpaces[i].avail = K;
+           FSMPageSetPageNum(&pageSpaces[i], R);
+           FSMPageSetSpace(&pageSpaces[i], K);
        }
 
        vacrelstats->fs_is_heap = true;
    }
 
    /* If new page has more than zero'th entry, insert it into heap */
-   if (avail > pageSpaces[0].avail)
+   if (avail > FSMPageGetSpace(&pageSpaces[0]))
    {
        /*
         * Notionally, we replace the zero'th entry with the new data, and
@@ -1169,15 +1169,15 @@ lazy_record_free_space(LVRelStats *vacrelstats,
 
            if (j >= n)
                break;
-           if (j + 1 < n && pageSpaces[j].avail > pageSpaces[j + 1].avail)
+           if (j + 1 < n && FSMPageGetSpace(&pageSpaces[j]) > FSMPageGetSpace(&pageSpaces[j + 1]))
                j++;
-           if (avail <= pageSpaces[j].avail)
+           if (avail <= FSMPageGetSpace(&pageSpaces[j]))
                break;
            pageSpaces[i] = pageSpaces[j];
            i = j;
        }
-       pageSpaces[i].blkno = page;
-       pageSpaces[i].avail = avail;
+       FSMPageSetPageNum(&pageSpaces[i], page);
+       FSMPageSetSpace(&pageSpaces[i], avail);
    }
 }
 
@@ -1210,14 +1210,14 @@ lazy_tid_reaped(ItemPointer itemptr, void *state)
 static void
 lazy_update_fsm(Relation onerel, LVRelStats *vacrelstats)
 {
-   PageFreeSpaceInfo *pageSpaces = vacrelstats->free_pages;
+   FSMPageData *pageSpaces = vacrelstats->free_pages;
    int         nPages = vacrelstats->num_free_pages;
 
    /*
     * Sort data into order, as required by RecordRelationFreeSpace.
     */
    if (nPages > 1)
-       qsort(pageSpaces, nPages, sizeof(PageFreeSpaceInfo),
+       qsort(pageSpaces, nPages, sizeof(FSMPageData),
              vac_cmp_page_spaces);
 
    RecordRelationFreeSpace(&onerel->rd_node, vacrelstats->tot_free_pages,
@@ -1257,12 +1257,14 @@ vac_cmp_itemptr(const void *left, const void *right)
 static int
 vac_cmp_page_spaces(const void *left, const void *right)
 {
-   PageFreeSpaceInfo *linfo = (PageFreeSpaceInfo *) left;
-   PageFreeSpaceInfo *rinfo = (PageFreeSpaceInfo *) right;
+   FSMPageData *linfo = (FSMPageData *) left;
+   FSMPageData *rinfo = (FSMPageData *) right;
+   BlockNumber lblkno = FSMPageGetPageNum(linfo);
+   BlockNumber rblkno = FSMPageGetPageNum(rinfo);
 
-   if (linfo->blkno < rinfo->blkno)
+   if (lblkno < rblkno)
        return -1;
-   else if (linfo->blkno > rinfo->blkno)
+   else if (lblkno > rblkno)
        return 1;
    return 0;
 }
index 7b66340f56c566ee0db305387de2d2acbfc00a7b..9373675b8cca6e1b3ce01ece6933c3a227076939 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/storage/freespace/freespace.c,v 1.59 2008/01/01 19:45:51 momjian Exp $
+ *   $PostgreSQL: pgsql/src/backend/storage/freespace/freespace.c,v 1.60 2008/03/10 02:04:09 tgl Exp $
  *
  *
  * NOTES:
@@ -143,7 +143,7 @@ static bool lookup_fsm_page_entry(FSMRelation *fsmrel, BlockNumber page,
 static void compact_fsm_storage(void);
 static void push_fsm_rels_after(FSMRelation *afterRel);
 static void pack_incoming_pages(FSMPageData *newLocation, int newPages,
-                   PageFreeSpaceInfo *pageSpaces, int nPages);
+                   FSMPageData *pageSpaces, int nPages);
 static void pack_existing_pages(FSMPageData *newLocation, int newPages,
                    FSMPageData *oldLocation, int oldPages);
 static int fsm_calc_request(FSMRelation *fsmrel);
@@ -375,7 +375,7 @@ void
 RecordRelationFreeSpace(RelFileNode *rel,
                        BlockNumber interestingPages,
                        int nPages,
-                       PageFreeSpaceInfo *pageSpaces)
+                       FSMPageData *pageSpaces)
 {
    FSMRelation *fsmrel;
 
@@ -415,14 +415,12 @@ RecordRelationFreeSpace(RelFileNode *rel,
 
            for (i = 0; i < nPages; i++)
            {
-               BlockNumber page = pageSpaces[i].blkno;
-               Size        avail = pageSpaces[i].avail;
+               BlockNumber page = FSMPageGetPageNum(&pageSpaces[i]);
 
                /* Check caller provides sorted data */
-               if (i > 0 && page <= pageSpaces[i - 1].blkno)
+               if (i > 0 && page <= FSMPageGetPageNum(&pageSpaces[i - 1]))
                    elog(ERROR, "free-space data is not in page order");
-               FSMPageSetPageNum(newLocation, page);
-               FSMPageSetSpace(newLocation, avail);
+               *newLocation = pageSpaces[i];
                newLocation++;
            }
            fsmrel->storedPages = nPages;
@@ -1534,7 +1532,7 @@ push_fsm_rels_after(FSMRelation *afterRel)
 
 static void
 pack_incoming_pages(FSMPageData *newLocation, int newPages,
-                   PageFreeSpaceInfo *pageSpaces, int nPages)
+                   FSMPageData *pageSpaces, int nPages)
 {
    int         histogram[HISTOGRAM_BINS];
    int         above,
@@ -1548,7 +1546,7 @@ pack_incoming_pages(FSMPageData *newLocation, int newPages,
    MemSet(histogram, 0, sizeof(histogram));
    for (i = 0; i < nPages; i++)
    {
-       Size        avail = pageSpaces[i].avail;
+       Size        avail = FSMPageGetSpace(&pageSpaces[i]);
 
        if (avail >= BLCKSZ)
            elog(ERROR, "bogus freespace amount");
@@ -1572,18 +1570,17 @@ pack_incoming_pages(FSMPageData *newLocation, int newPages,
    /* And copy the appropriate data */
    for (i = 0; i < nPages; i++)
    {
-       BlockNumber page = pageSpaces[i].blkno;
-       Size        avail = pageSpaces[i].avail;
+       BlockNumber page = FSMPageGetPageNum(&pageSpaces[i]);
+       Size        avail = FSMPageGetSpace(&pageSpaces[i]);
 
        /* Check caller provides sorted data */
-       if (i > 0 && page <= pageSpaces[i - 1].blkno)
+       if (i > 0 && page <= FSMPageGetPageNum(&pageSpaces[i - 1]))
            elog(ERROR, "free-space data is not in page order");
        /* Save this page? */
        if (avail >= thresholdU ||
            (avail >= thresholdL && (--binct >= 0)))
        {
-           FSMPageSetPageNum(newLocation, page);
-           FSMPageSetSpace(newLocation, avail);
+           *newLocation = pageSpaces[i];
            newLocation++;
            newPages--;
        }
index 0ef828ed54d8ac42ce70c75cc26b038aa7215df8..86dd22647c358abc386da571edc67e79c45de8c9 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/storage/freespace.h,v 1.27 2008/01/01 19:45:59 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/storage/freespace.h,v 1.28 2008/03/10 02:04:10 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "storage/itemptr.h"
 
 
-/*
- * exported types
- */
-typedef struct PageFreeSpaceInfo
-{
-   BlockNumber blkno;          /* which page in relation */
-   Size        avail;          /* space available on this page */
-} PageFreeSpaceInfo;
-
-
 /* Initial value for average-request moving average */
 #define INITIAL_AVERAGE ((Size) (BLCKSZ / 32))
 
@@ -144,7 +134,7 @@ extern Size GetAvgFSMRequestSize(RelFileNode *rel);
 extern void RecordRelationFreeSpace(RelFileNode *rel,
                        BlockNumber interestingPages,
                        int nPages,
-                       PageFreeSpaceInfo *pageSpaces);
+                       FSMPageData *pageSpaces);
 
 extern BlockNumber GetFreeIndexPage(RelFileNode *rel);
 extern void RecordIndexFreeSpace(RelFileNode *rel,