Commit 3fcc7e8e authored by Tom Lane's avatar Tom Lane

Reduce memory consumption during VACUUM of large relations, by using

FSMPageData (6 bytes) instead of PageFreeSpaceInfo (8 or 16 bytes)
for the temporary array of page-free-space information.

Itagaki Takahiro
parent 9537739f
......@@ -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++;
}
}
......
......@@ -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;
}
......@@ -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--;
}
......
......@@ -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 $
*
*-------------------------------------------------------------------------
*/
......@@ -18,16 +18,6 @@
#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,
......
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