mirror of
https://github.com/postgres/postgres.git
synced 2025-04-24 10:47:04 +03:00
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
This commit is contained in:
parent
9537739f7f
commit
3fcc7e8e18
@ -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,
|
|||||||
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,
|
|||||||
*/
|
*/
|
||||||
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,
|
|||||||
|
|
||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
/* 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,
|
|||||||
|
|
||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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 @@
|
|||||||
* 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,
|
|||||||
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
|
|||||||
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,
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
/* 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 @@
|
|||||||
* 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 @@
|
|||||||
#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);
|
|||||||
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,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user