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