mirror of
https://github.com/postgres/postgres.git
synced 2025-07-24 14:22:24 +03:00
Vacuum cleanup.
This commit is contained in:
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.72 1998/08/19 19:59:43 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.73 1998/08/19 22:01:18 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -79,12 +79,12 @@ static void vc_shutdown(void);
|
|||||||
static void vc_vacuum(NameData *VacRelP, bool analyze, List *va_cols);
|
static void vc_vacuum(NameData *VacRelP, bool analyze, List *va_cols);
|
||||||
static VRelList vc_getrels(NameData *VacRelP);
|
static VRelList vc_getrels(NameData *VacRelP);
|
||||||
static void vc_vacone(Oid relid, bool analyze, List *va_cols);
|
static void vc_vacone(Oid relid, bool analyze, List *va_cols);
|
||||||
static void vc_scanheap(VRelStats *vacrelstats, Relation onerel, VPageList Vvpl, VPageList Fvpl);
|
static void vc_scanheap(VRelStats *vacrelstats, Relation onerel, VPageList vacuum_pages, VPageList fraged_pages);
|
||||||
static void vc_rpfheap(VRelStats *vacrelstats, Relation onerel, VPageList Vvpl, VPageList Fvpl, int nindices, Relation *Irel);
|
static void vc_rpfheap(VRelStats *vacrelstats, Relation onerel, VPageList vacuum_pages, VPageList fraged_pages, int nindices, Relation *Irel);
|
||||||
static void vc_vacheap(VRelStats *vacrelstats, Relation onerel, VPageList vpl);
|
static void vc_vacheap(VRelStats *vacrelstats, Relation onerel, VPageList vpl);
|
||||||
static void vc_vacpage(Page page, VPageDescr vpd);
|
static void vc_vacpage(Page page, VPageDescr vpd);
|
||||||
static void vc_vaconeind(VPageList vpl, Relation indrel, int nhtups);
|
static void vc_vaconeind(VPageList vpl, Relation indrel, int num_tuples);
|
||||||
static void vc_scanoneind(Relation indrel, int nhtups);
|
static void vc_scanoneind(Relation indrel, int num_tuples);
|
||||||
static void vc_attrstats(Relation onerel, VRelStats *vacrelstats, HeapTuple tuple);
|
static void vc_attrstats(Relation onerel, VRelStats *vacrelstats, HeapTuple tuple);
|
||||||
static void vc_bucketcpy(AttributeTupleForm attr, Datum value, Datum *bucket, int16 *bucket_len);
|
static void vc_bucketcpy(AttributeTupleForm attr, Datum value, Datum *bucket, int16 *bucket_len);
|
||||||
static void vc_updstats(Oid relid, int num_pages, int num_tuples, bool hasindex, VRelStats *vacrelstats);
|
static void vc_updstats(Oid relid, int num_pages, int num_tuples, bool hasindex, VRelStats *vacrelstats);
|
||||||
@ -373,9 +373,9 @@ vc_vacone(Oid relid, bool analyze, List *va_cols)
|
|||||||
HeapTuple tuple,
|
HeapTuple tuple,
|
||||||
typetuple;
|
typetuple;
|
||||||
Relation onerel;
|
Relation onerel;
|
||||||
VPageListData Vvpl; /* List of pages to vacuum and/or clean
|
VPageListData vacuum_pages; /* List of pages to vacuum and/or clean
|
||||||
* indices */
|
* indices */
|
||||||
VPageListData Fvpl; /* List of pages with space enough for
|
VPageListData fraged_pages; /* List of pages with space enough for
|
||||||
* re-using */
|
* re-using */
|
||||||
VPageDescr *vpp;
|
VPageDescr *vpp;
|
||||||
Relation *Irel;
|
Relation *Irel;
|
||||||
@ -517,8 +517,8 @@ vc_vacone(Oid relid, bool analyze, List *va_cols)
|
|||||||
RelationSetLockForWrite(onerel);
|
RelationSetLockForWrite(onerel);
|
||||||
|
|
||||||
/* scan it */
|
/* scan it */
|
||||||
Vvpl.vpl_num_pages = Fvpl.vpl_num_pages = 0;
|
vacuum_pages.vpl_num_pages = fraged_pages.vpl_num_pages = 0;
|
||||||
vc_scanheap(vacrelstats, onerel, &Vvpl, &Fvpl);
|
vc_scanheap(vacrelstats, onerel, &vacuum_pages, &fraged_pages);
|
||||||
|
|
||||||
/* Now open indices */
|
/* Now open indices */
|
||||||
Irel = (Relation *) NULL;
|
Irel = (Relation *) NULL;
|
||||||
@ -532,10 +532,10 @@ vc_vacone(Oid relid, bool analyze, List *va_cols)
|
|||||||
/* Clean/scan index relation(s) */
|
/* Clean/scan index relation(s) */
|
||||||
if (Irel != (Relation *) NULL)
|
if (Irel != (Relation *) NULL)
|
||||||
{
|
{
|
||||||
if (Vvpl.vpl_num_pages > 0)
|
if (vacuum_pages.vpl_num_pages > 0)
|
||||||
{
|
{
|
||||||
for (i = 0; i < nindices; i++)
|
for (i = 0; i < nindices; i++)
|
||||||
vc_vaconeind(&Vvpl, Irel[i], vacrelstats->num_tuples);
|
vc_vaconeind(&vacuum_pages, Irel[i], vacrelstats->num_tuples);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
/* just scan indices to update statistic */
|
/* just scan indices to update statistic */
|
||||||
@ -545,25 +545,25 @@ vc_vacone(Oid relid, bool analyze, List *va_cols)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Fvpl.vpl_num_pages > 0) /* Try to shrink heap */
|
if (fraged_pages.vpl_num_pages > 0) /* Try to shrink heap */
|
||||||
vc_rpfheap(vacrelstats, onerel, &Vvpl, &Fvpl, nindices, Irel);
|
vc_rpfheap(vacrelstats, onerel, &vacuum_pages, &fraged_pages, nindices, Irel);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (Irel != (Relation *) NULL)
|
if (Irel != (Relation *) NULL)
|
||||||
vc_clsindices(nindices, Irel);
|
vc_clsindices(nindices, Irel);
|
||||||
if (Vvpl.vpl_num_pages > 0)/* Clean pages from Vvpl list */
|
if (vacuum_pages.vpl_num_pages > 0)/* Clean pages from vacuum_pages list */
|
||||||
vc_vacheap(vacrelstats, onerel, &Vvpl);
|
vc_vacheap(vacrelstats, onerel, &vacuum_pages);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ok - free Vvpl list of reapped pages */
|
/* ok - free vacuum_pages list of reapped pages */
|
||||||
if (Vvpl.vpl_num_pages > 0)
|
if (vacuum_pages.vpl_num_pages > 0)
|
||||||
{
|
{
|
||||||
vpp = Vvpl.vpl_pagedesc;
|
vpp = vacuum_pages.vpl_pagedesc;
|
||||||
for (i = 0; i < Vvpl.vpl_num_pages; i++, vpp++)
|
for (i = 0; i < vacuum_pages.vpl_num_pages; i++, vpp++)
|
||||||
pfree(*vpp);
|
pfree(*vpp);
|
||||||
pfree(Vvpl.vpl_pagedesc);
|
pfree(vacuum_pages.vpl_pagedesc);
|
||||||
if (Fvpl.vpl_num_pages > 0)
|
if (fraged_pages.vpl_num_pages > 0)
|
||||||
pfree(Fvpl.vpl_pagedesc);
|
pfree(fraged_pages.vpl_pagedesc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* all done with this class */
|
/* all done with this class */
|
||||||
@ -582,15 +582,15 @@ vc_vacone(Oid relid, bool analyze, List *va_cols)
|
|||||||
/*
|
/*
|
||||||
* vc_scanheap() -- scan an open heap relation
|
* vc_scanheap() -- scan an open heap relation
|
||||||
*
|
*
|
||||||
* This routine sets commit times, constructs Vvpl list of
|
* This routine sets commit times, constructs vacuum_pages list of
|
||||||
* empty/uninitialized pages and pages with dead tuples and
|
* empty/uninitialized pages and pages with dead tuples and
|
||||||
* ~LP_USED line pointers, constructs Fvpl list of pages
|
* ~LP_USED line pointers, constructs fraged_pages list of pages
|
||||||
* appropriate for purposes of shrinking and maintains statistics
|
* appropriate for purposes of shrinking and maintains statistics
|
||||||
* on the number of live tuples in a heap.
|
* on the number of live tuples in a heap.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
vc_scanheap(VRelStats *vacrelstats, Relation onerel,
|
vc_scanheap(VRelStats *vacrelstats, Relation onerel,
|
||||||
VPageList Vvpl, VPageList Fvpl)
|
VPageList vacuum_pages, VPageList fraged_pages)
|
||||||
{
|
{
|
||||||
int nblocks,
|
int nblocks,
|
||||||
blkno;
|
blkno;
|
||||||
@ -616,9 +616,9 @@ vc_scanheap(VRelStats *vacrelstats, Relation onerel,
|
|||||||
empty_pages,
|
empty_pages,
|
||||||
new_pages,
|
new_pages,
|
||||||
changed_pages,
|
changed_pages,
|
||||||
nemend;
|
empty_end_pages;
|
||||||
Size frsize,
|
Size free_size,
|
||||||
frsusf;
|
usable_free_size;
|
||||||
Size min_tlen = MAXTUPLEN;
|
Size min_tlen = MAXTUPLEN;
|
||||||
Size max_tlen = 0;
|
Size max_tlen = 0;
|
||||||
int32 i;
|
int32 i;
|
||||||
@ -628,8 +628,9 @@ vc_scanheap(VRelStats *vacrelstats, Relation onerel,
|
|||||||
|
|
||||||
getrusage(RUSAGE_SELF, &ru0);
|
getrusage(RUSAGE_SELF, &ru0);
|
||||||
|
|
||||||
tups_vacuumed = num_tuples = nunused = ncrash = empty_pages = new_pages = changed_pages = nemend = 0;
|
tups_vacuumed = num_tuples = nunused = ncrash = empty_pages =
|
||||||
frsize = frsusf = 0;
|
new_pages = changed_pages = empty_end_pages = 0;
|
||||||
|
free_size = usable_free_size = 0;
|
||||||
|
|
||||||
relname = (RelationGetRelationName(onerel))->data;
|
relname = (RelationGetRelationName(onerel))->data;
|
||||||
|
|
||||||
@ -653,10 +654,10 @@ vc_scanheap(VRelStats *vacrelstats, Relation onerel,
|
|||||||
relname, blkno);
|
relname, blkno);
|
||||||
PageInit(page, BufferGetPageSize(buf), 0);
|
PageInit(page, BufferGetPageSize(buf), 0);
|
||||||
vpc->vpd_free = ((PageHeader) page)->pd_upper - ((PageHeader) page)->pd_lower;
|
vpc->vpd_free = ((PageHeader) page)->pd_upper - ((PageHeader) page)->pd_lower;
|
||||||
frsize += (vpc->vpd_free - sizeof(ItemIdData));
|
free_size += (vpc->vpd_free - sizeof(ItemIdData));
|
||||||
new_pages++;
|
new_pages++;
|
||||||
nemend++;
|
empty_end_pages++;
|
||||||
vc_reappage(Vvpl, vpc);
|
vc_reappage(vacuum_pages, vpc);
|
||||||
WriteBuffer(buf);
|
WriteBuffer(buf);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -664,10 +665,10 @@ vc_scanheap(VRelStats *vacrelstats, Relation onerel,
|
|||||||
if (PageIsEmpty(page))
|
if (PageIsEmpty(page))
|
||||||
{
|
{
|
||||||
vpc->vpd_free = ((PageHeader) page)->pd_upper - ((PageHeader) page)->pd_lower;
|
vpc->vpd_free = ((PageHeader) page)->pd_upper - ((PageHeader) page)->pd_lower;
|
||||||
frsize += (vpc->vpd_free - sizeof(ItemIdData));
|
free_size += (vpc->vpd_free - sizeof(ItemIdData));
|
||||||
empty_pages++;
|
empty_pages++;
|
||||||
nemend++;
|
empty_end_pages++;
|
||||||
vc_reappage(Vvpl, vpc);
|
vc_reappage(vacuum_pages, vpc);
|
||||||
ReleaseBuffer(buf);
|
ReleaseBuffer(buf);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -836,23 +837,23 @@ vc_scanheap(VRelStats *vacrelstats, Relation onerel,
|
|||||||
{ /* Some tuples are gone */
|
{ /* Some tuples are gone */
|
||||||
PageRepairFragmentation(tempPage);
|
PageRepairFragmentation(tempPage);
|
||||||
vpc->vpd_free = ((PageHeader) tempPage)->pd_upper - ((PageHeader) tempPage)->pd_lower;
|
vpc->vpd_free = ((PageHeader) tempPage)->pd_upper - ((PageHeader) tempPage)->pd_lower;
|
||||||
frsize += vpc->vpd_free;
|
free_size += vpc->vpd_free;
|
||||||
vc_reappage(Vvpl, vpc);
|
vc_reappage(vacuum_pages, vpc);
|
||||||
pfree(tempPage);
|
pfree(tempPage);
|
||||||
tempPage = (Page) NULL;
|
tempPage = (Page) NULL;
|
||||||
}
|
}
|
||||||
else if (vpc->vpd_offsets_free > 0)
|
else if (vpc->vpd_offsets_free > 0)
|
||||||
{ /* there are only ~LP_USED line pointers */
|
{ /* there are only ~LP_USED line pointers */
|
||||||
vpc->vpd_free = ((PageHeader) page)->pd_upper - ((PageHeader) page)->pd_lower;
|
vpc->vpd_free = ((PageHeader) page)->pd_upper - ((PageHeader) page)->pd_lower;
|
||||||
frsize += vpc->vpd_free;
|
free_size += vpc->vpd_free;
|
||||||
vc_reappage(Vvpl, vpc);
|
vc_reappage(vacuum_pages, vpc);
|
||||||
}
|
}
|
||||||
if (dobufrel)
|
if (dobufrel)
|
||||||
ReleaseBuffer(buf);
|
ReleaseBuffer(buf);
|
||||||
if (notup)
|
if (notup)
|
||||||
nemend++;
|
empty_end_pages++;
|
||||||
else
|
else
|
||||||
nemend = 0;
|
empty_end_pages = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pfree(vpc);
|
pfree(vpc);
|
||||||
@ -866,28 +867,28 @@ vc_scanheap(VRelStats *vacrelstats, Relation onerel,
|
|||||||
vacrelstats->min_tlen = min_tlen;
|
vacrelstats->min_tlen = min_tlen;
|
||||||
vacrelstats->max_tlen = max_tlen;
|
vacrelstats->max_tlen = max_tlen;
|
||||||
|
|
||||||
Vvpl->vpl_empty_end_pages = nemend;
|
vacuum_pages->vpl_empty_end_pages = empty_end_pages;
|
||||||
Fvpl->vpl_empty_end_pages = nemend;
|
fraged_pages->vpl_empty_end_pages = empty_end_pages;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Try to make Fvpl keeping in mind that we can't use free space of
|
* Try to make fraged_pages keeping in mind that we can't use free space of
|
||||||
* "empty" end-pages and last page if it reapped.
|
* "empty" end-pages and last page if it reapped.
|
||||||
*/
|
*/
|
||||||
if (do_shrinking && Vvpl->vpl_num_pages - nemend > 0)
|
if (do_shrinking && vacuum_pages->vpl_num_pages - empty_end_pages > 0)
|
||||||
{
|
{
|
||||||
int nusf; /* blocks usefull for re-using */
|
int nusf; /* blocks usefull for re-using */
|
||||||
|
|
||||||
nusf = Vvpl->vpl_num_pages - nemend;
|
nusf = vacuum_pages->vpl_num_pages - empty_end_pages;
|
||||||
if ((Vvpl->vpl_pagedesc[nusf - 1])->vpd_blkno == nblocks - nemend - 1)
|
if ((vacuum_pages->vpl_pagedesc[nusf - 1])->vpd_blkno == nblocks - empty_end_pages - 1)
|
||||||
nusf--;
|
nusf--;
|
||||||
|
|
||||||
for (i = 0; i < nusf; i++)
|
for (i = 0; i < nusf; i++)
|
||||||
{
|
{
|
||||||
vp = Vvpl->vpl_pagedesc[i];
|
vp = vacuum_pages->vpl_pagedesc[i];
|
||||||
if (vc_enough_space(vp, min_tlen))
|
if (vc_enough_space(vp, min_tlen))
|
||||||
{
|
{
|
||||||
vc_vpinsert(Fvpl, vp);
|
vc_vpinsert(fraged_pages, vp);
|
||||||
frsusf += vp->vpd_free;
|
usable_free_size += vp->vpd_free;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -896,9 +897,9 @@ vc_scanheap(VRelStats *vacrelstats, Relation onerel,
|
|||||||
|
|
||||||
elog(MESSAGE_LEVEL, "Pages %u: Changed %u, Reapped %u, Empty %u, New %u; \
|
elog(MESSAGE_LEVEL, "Pages %u: Changed %u, Reapped %u, Empty %u, New %u; \
|
||||||
Tup %u: Vac %u, Crash %u, UnUsed %u, MinLen %u, MaxLen %u; Re-using: Free/Avail. Space %u/%u; EndEmpty/Avail. Pages %u/%u. Elapsed %u/%u sec.",
|
Tup %u: Vac %u, Crash %u, UnUsed %u, MinLen %u, MaxLen %u; Re-using: Free/Avail. Space %u/%u; EndEmpty/Avail. Pages %u/%u. Elapsed %u/%u sec.",
|
||||||
nblocks, changed_pages, Vvpl->vpl_num_pages, empty_pages, new_pages,
|
nblocks, changed_pages, vacuum_pages->vpl_num_pages, empty_pages, new_pages,
|
||||||
num_tuples, tups_vacuumed, ncrash, nunused, min_tlen, max_tlen,
|
num_tuples, tups_vacuumed, ncrash, nunused, min_tlen, max_tlen,
|
||||||
frsize, frsusf, nemend, Fvpl->vpl_num_pages,
|
free_size, usable_free_size, empty_end_pages, fraged_pages->vpl_num_pages,
|
||||||
ru1.ru_stime.tv_sec - ru0.ru_stime.tv_sec,
|
ru1.ru_stime.tv_sec - ru0.ru_stime.tv_sec,
|
||||||
ru1.ru_utime.tv_sec - ru0.ru_utime.tv_sec);
|
ru1.ru_utime.tv_sec - ru0.ru_utime.tv_sec);
|
||||||
|
|
||||||
@ -917,12 +918,12 @@ Tup %u: Vac %u, Crash %u, UnUsed %u, MinLen %u, MaxLen %u; Re-using: Free/Avail.
|
|||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
vc_rpfheap(VRelStats *vacrelstats, Relation onerel,
|
vc_rpfheap(VRelStats *vacrelstats, Relation onerel,
|
||||||
VPageList Vvpl, VPageList Fvpl, int nindices, Relation *Irel)
|
VPageList vacuum_pages, VPageList fraged_pages, int nindices, Relation *Irel)
|
||||||
{
|
{
|
||||||
TransactionId myXID;
|
TransactionId myXID;
|
||||||
CommandId myCID;
|
CommandId myCID;
|
||||||
Buffer buf,
|
Buffer buf,
|
||||||
ToBuf;
|
cur_buffer;
|
||||||
int nblocks,
|
int nblocks,
|
||||||
blkno;
|
blkno;
|
||||||
Page page,
|
Page page,
|
||||||
@ -940,21 +941,21 @@ vc_rpfheap(VRelStats *vacrelstats, Relation onerel,
|
|||||||
char *inulls = NULL;
|
char *inulls = NULL;
|
||||||
InsertIndexResult iresult;
|
InsertIndexResult iresult;
|
||||||
VPageListData Nvpl;
|
VPageListData Nvpl;
|
||||||
VPageDescr ToVpd = NULL,
|
VPageDescr cur_page = NULL,
|
||||||
Fvplast,
|
last_fraged_page,
|
||||||
Vvplast,
|
last_vacuum_page,
|
||||||
vpc,
|
vpc,
|
||||||
*vpp;
|
*vpp;
|
||||||
int ToVpI = 0;
|
int cur_item = 0;
|
||||||
IndDesc *Idesc,
|
IndDesc *Idesc,
|
||||||
*idcur;
|
*idcur;
|
||||||
int Fblklast,
|
int last_fraged_block,
|
||||||
Vblklast,
|
last_vacuum_block,
|
||||||
i;
|
i;
|
||||||
Size tlen;
|
Size tuple_len;
|
||||||
int nmoved,
|
int num_moved,
|
||||||
Fnum_pages,
|
num_fraged_pages,
|
||||||
Vnum_pages;
|
vacuumed_pages;
|
||||||
int checked_moved,
|
int checked_moved,
|
||||||
num_tuples;
|
num_tuples;
|
||||||
bool isempty,
|
bool isempty,
|
||||||
@ -976,25 +977,25 @@ vc_rpfheap(VRelStats *vacrelstats, Relation onerel,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Nvpl.vpl_num_pages = 0;
|
Nvpl.vpl_num_pages = 0;
|
||||||
Fnum_pages = Fvpl->vpl_num_pages;
|
num_fraged_pages = fraged_pages->vpl_num_pages;
|
||||||
Fvplast = Fvpl->vpl_pagedesc[Fnum_pages - 1];
|
last_fraged_page = fraged_pages->vpl_pagedesc[num_fraged_pages - 1];
|
||||||
Fblklast = Fvplast->vpd_blkno;
|
last_fraged_block = last_fraged_page->vpd_blkno;
|
||||||
Assert(Vvpl->vpl_num_pages > Vvpl->vpl_empty_end_pages);
|
Assert(vacuum_pages->vpl_num_pages > vacuum_pages->vpl_empty_end_pages);
|
||||||
Vnum_pages = Vvpl->vpl_num_pages - Vvpl->vpl_empty_end_pages;
|
vacuumed_pages = vacuum_pages->vpl_num_pages - vacuum_pages->vpl_empty_end_pages;
|
||||||
Vvplast = Vvpl->vpl_pagedesc[Vnum_pages - 1];
|
last_vacuum_page = vacuum_pages->vpl_pagedesc[vacuumed_pages - 1];
|
||||||
Vblklast = Vvplast->vpd_blkno;
|
last_vacuum_block = last_vacuum_page->vpd_blkno;
|
||||||
Assert(Vblklast >= Fblklast);
|
Assert(last_vacuum_block >= last_fraged_block);
|
||||||
ToBuf = InvalidBuffer;
|
cur_buffer = InvalidBuffer;
|
||||||
nmoved = 0;
|
num_moved = 0;
|
||||||
|
|
||||||
vpc = (VPageDescr) palloc(sizeof(VPageDescrData) + MaxOffsetNumber * sizeof(OffsetNumber));
|
vpc = (VPageDescr) palloc(sizeof(VPageDescrData) + MaxOffsetNumber * sizeof(OffsetNumber));
|
||||||
vpc->vpd_offsets_used = vpc->vpd_offsets_free = 0;
|
vpc->vpd_offsets_used = vpc->vpd_offsets_free = 0;
|
||||||
|
|
||||||
nblocks = vacrelstats->num_pages;
|
nblocks = vacrelstats->num_pages;
|
||||||
for (blkno = nblocks - Vvpl->vpl_empty_end_pages - 1;; blkno--)
|
for (blkno = nblocks - vacuum_pages->vpl_empty_end_pages - 1;; blkno--)
|
||||||
{
|
{
|
||||||
/* if it's reapped page and it was used by me - quit */
|
/* if it's reapped page and it was used by me - quit */
|
||||||
if (blkno == Fblklast && Fvplast->vpd_offsets_used > 0)
|
if (blkno == last_fraged_block && last_fraged_page->vpd_offsets_used > 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
buf = ReadBuffer(onerel, blkno);
|
buf = ReadBuffer(onerel, blkno);
|
||||||
@ -1005,31 +1006,31 @@ vc_rpfheap(VRelStats *vacrelstats, Relation onerel,
|
|||||||
isempty = PageIsEmpty(page);
|
isempty = PageIsEmpty(page);
|
||||||
|
|
||||||
dowrite = false;
|
dowrite = false;
|
||||||
if (blkno == Vblklast) /* it's reapped page */
|
if (blkno == last_vacuum_block) /* it's reapped page */
|
||||||
{
|
{
|
||||||
if (Vvplast->vpd_offsets_free > 0) /* there are dead tuples */
|
if (last_vacuum_page->vpd_offsets_free > 0) /* there are dead tuples */
|
||||||
{ /* on this page - clean */
|
{ /* on this page - clean */
|
||||||
Assert(!isempty);
|
Assert(!isempty);
|
||||||
vc_vacpage(page, Vvplast);
|
vc_vacpage(page, last_vacuum_page);
|
||||||
dowrite = true;
|
dowrite = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Assert(isempty);
|
Assert(isempty);
|
||||||
--Vnum_pages;
|
--vacuumed_pages;
|
||||||
Assert(Vnum_pages > 0);
|
Assert(vacuumed_pages > 0);
|
||||||
/* get prev reapped page from Vvpl */
|
/* get prev reapped page from vacuum_pages */
|
||||||
Vvplast = Vvpl->vpl_pagedesc[Vnum_pages - 1];
|
last_vacuum_page = vacuum_pages->vpl_pagedesc[vacuumed_pages - 1];
|
||||||
Vblklast = Vvplast->vpd_blkno;
|
last_vacuum_block = last_vacuum_page->vpd_blkno;
|
||||||
if (blkno == Fblklast) /* this page in Fvpl too */
|
if (blkno == last_fraged_block) /* this page in fraged_pages too */
|
||||||
{
|
{
|
||||||
--Fnum_pages;
|
--num_fraged_pages;
|
||||||
Assert(Fnum_pages > 0);
|
Assert(num_fraged_pages > 0);
|
||||||
Assert(Fvplast->vpd_offsets_used == 0);
|
Assert(last_fraged_page->vpd_offsets_used == 0);
|
||||||
/* get prev reapped page from Fvpl */
|
/* get prev reapped page from fraged_pages */
|
||||||
Fvplast = Fvpl->vpl_pagedesc[Fnum_pages - 1];
|
last_fraged_page = fraged_pages->vpl_pagedesc[num_fraged_pages - 1];
|
||||||
Fblklast = Fvplast->vpd_blkno;
|
last_fraged_block = last_fraged_page->vpd_blkno;
|
||||||
}
|
}
|
||||||
Assert(Fblklast <= Vblklast);
|
Assert(last_fraged_block <= last_vacuum_block);
|
||||||
if (isempty)
|
if (isempty)
|
||||||
{
|
{
|
||||||
ReleaseBuffer(buf);
|
ReleaseBuffer(buf);
|
||||||
@ -1051,54 +1052,54 @@ vc_rpfheap(VRelStats *vacrelstats, Relation onerel,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
tuple = (HeapTuple) PageGetItem(page, itemid);
|
tuple = (HeapTuple) PageGetItem(page, itemid);
|
||||||
tlen = tuple->t_len;
|
tuple_len = tuple->t_len;
|
||||||
|
|
||||||
/* try to find new page for this tuple */
|
/* try to find new page for this tuple */
|
||||||
if (ToBuf == InvalidBuffer ||
|
if (cur_buffer == InvalidBuffer ||
|
||||||
!vc_enough_space(ToVpd, tlen))
|
!vc_enough_space(cur_page, tuple_len))
|
||||||
{
|
{
|
||||||
if (ToBuf != InvalidBuffer)
|
if (cur_buffer != InvalidBuffer)
|
||||||
{
|
{
|
||||||
WriteBuffer(ToBuf);
|
WriteBuffer(cur_buffer);
|
||||||
ToBuf = InvalidBuffer;
|
cur_buffer = InvalidBuffer;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If no one tuple can't be added to this page -
|
* If no one tuple can't be added to this page -
|
||||||
* remove page from Fvpl. - vadim 11/27/96
|
* remove page from fraged_pages. - vadim 11/27/96
|
||||||
*
|
*
|
||||||
* But we can't remove last page - this is our
|
* But we can't remove last page - this is our
|
||||||
* "show-stopper" !!! - vadim 02/25/98
|
* "show-stopper" !!! - vadim 02/25/98
|
||||||
*/
|
*/
|
||||||
if (ToVpd != Fvplast &&
|
if (cur_page != last_fraged_page &&
|
||||||
!vc_enough_space(ToVpd, vacrelstats->min_tlen))
|
!vc_enough_space(cur_page, vacrelstats->min_tlen))
|
||||||
{
|
{
|
||||||
Assert(Fnum_pages > ToVpI + 1);
|
Assert(num_fraged_pages > cur_item + 1);
|
||||||
memmove(Fvpl->vpl_pagedesc + ToVpI,
|
memmove(fraged_pages->vpl_pagedesc + cur_item,
|
||||||
Fvpl->vpl_pagedesc + ToVpI + 1,
|
fraged_pages->vpl_pagedesc + cur_item + 1,
|
||||||
sizeof(VPageDescr *) * (Fnum_pages - ToVpI - 1));
|
sizeof(VPageDescr *) * (num_fraged_pages - cur_item - 1));
|
||||||
Fnum_pages--;
|
num_fraged_pages--;
|
||||||
Assert(Fvplast == Fvpl->vpl_pagedesc[Fnum_pages - 1]);
|
Assert(last_fraged_page == fraged_pages->vpl_pagedesc[num_fraged_pages - 1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (i = 0; i < Fnum_pages; i++)
|
for (i = 0; i < num_fraged_pages; i++)
|
||||||
{
|
{
|
||||||
if (vc_enough_space(Fvpl->vpl_pagedesc[i], tlen))
|
if (vc_enough_space(fraged_pages->vpl_pagedesc[i], tuple_len))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (i == Fnum_pages)
|
if (i == num_fraged_pages)
|
||||||
break; /* can't move item anywhere */
|
break; /* can't move item anywhere */
|
||||||
ToVpI = i;
|
cur_item = i;
|
||||||
ToVpd = Fvpl->vpl_pagedesc[ToVpI];
|
cur_page = fraged_pages->vpl_pagedesc[cur_item];
|
||||||
ToBuf = ReadBuffer(onerel, ToVpd->vpd_blkno);
|
cur_buffer = ReadBuffer(onerel, cur_page->vpd_blkno);
|
||||||
ToPage = BufferGetPage(ToBuf);
|
ToPage = BufferGetPage(cur_buffer);
|
||||||
/* if this page was not used before - clean it */
|
/* if this page was not used before - clean it */
|
||||||
if (!PageIsEmpty(ToPage) && ToVpd->vpd_offsets_used == 0)
|
if (!PageIsEmpty(ToPage) && cur_page->vpd_offsets_used == 0)
|
||||||
vc_vacpage(ToPage, ToVpd);
|
vc_vacpage(ToPage, cur_page);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy tuple */
|
/* copy tuple */
|
||||||
newtup = (HeapTuple) palloc(tlen);
|
newtup = (HeapTuple) palloc(tuple_len);
|
||||||
memmove((char *) newtup, (char *) tuple, tlen);
|
memmove((char *) newtup, (char *) tuple, tuple_len);
|
||||||
|
|
||||||
/* store transaction information */
|
/* store transaction information */
|
||||||
TransactionIdStore(myXID, &(newtup->t_xmin));
|
TransactionIdStore(myXID, &(newtup->t_xmin));
|
||||||
@ -1109,19 +1110,19 @@ vc_rpfheap(VRelStats *vacrelstats, Relation onerel,
|
|||||||
newtup->t_infomask |= HEAP_XMAX_INVALID;
|
newtup->t_infomask |= HEAP_XMAX_INVALID;
|
||||||
|
|
||||||
/* add tuple to the page */
|
/* add tuple to the page */
|
||||||
newoff = PageAddItem(ToPage, (Item) newtup, tlen,
|
newoff = PageAddItem(ToPage, (Item) newtup, tuple_len,
|
||||||
InvalidOffsetNumber, LP_USED);
|
InvalidOffsetNumber, LP_USED);
|
||||||
if (newoff == InvalidOffsetNumber)
|
if (newoff == InvalidOffsetNumber)
|
||||||
{
|
{
|
||||||
elog(ERROR, "\
|
elog(ERROR, "\
|
||||||
failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)",
|
failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)",
|
||||||
tlen, ToVpd->vpd_blkno, ToVpd->vpd_free,
|
tuple_len, cur_page->vpd_blkno, cur_page->vpd_free,
|
||||||
ToVpd->vpd_offsets_used, ToVpd->vpd_offsets_free);
|
cur_page->vpd_offsets_used, cur_page->vpd_offsets_free);
|
||||||
}
|
}
|
||||||
newitemid = PageGetItemId(ToPage, newoff);
|
newitemid = PageGetItemId(ToPage, newoff);
|
||||||
pfree(newtup);
|
pfree(newtup);
|
||||||
newtup = (HeapTuple) PageGetItem(ToPage, newitemid);
|
newtup = (HeapTuple) PageGetItem(ToPage, newitemid);
|
||||||
ItemPointerSet(&(newtup->t_ctid), ToVpd->vpd_blkno, newoff);
|
ItemPointerSet(&(newtup->t_ctid), cur_page->vpd_blkno, newoff);
|
||||||
|
|
||||||
/* now logically delete end-tuple */
|
/* now logically delete end-tuple */
|
||||||
TransactionIdStore(myXID, &(tuple->t_xmax));
|
TransactionIdStore(myXID, &(tuple->t_xmax));
|
||||||
@ -1129,9 +1130,9 @@ failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)",
|
|||||||
/* set xmax to unknown */
|
/* set xmax to unknown */
|
||||||
tuple->t_infomask &= ~(HEAP_XMAX_INVALID | HEAP_XMAX_COMMITTED);
|
tuple->t_infomask &= ~(HEAP_XMAX_INVALID | HEAP_XMAX_COMMITTED);
|
||||||
|
|
||||||
ToVpd->vpd_offsets_used++;
|
cur_page->vpd_offsets_used++;
|
||||||
nmoved++;
|
num_moved++;
|
||||||
ToVpd->vpd_free = ((PageHeader) ToPage)->pd_upper - ((PageHeader) ToPage)->pd_lower;
|
cur_page->vpd_free = ((PageHeader) ToPage)->pd_upper - ((PageHeader) ToPage)->pd_lower;
|
||||||
vpc->vpd_offsets[vpc->vpd_offsets_free++] = offnum;
|
vpc->vpd_offsets[vpc->vpd_offsets_free++] = offnum;
|
||||||
|
|
||||||
/* insert index' tuples if needed */
|
/* insert index' tuples if needed */
|
||||||
@ -1177,13 +1178,13 @@ failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)",
|
|||||||
|
|
||||||
blkno++; /* new number of blocks */
|
blkno++; /* new number of blocks */
|
||||||
|
|
||||||
if (ToBuf != InvalidBuffer)
|
if (cur_buffer != InvalidBuffer)
|
||||||
{
|
{
|
||||||
Assert(nmoved > 0);
|
Assert(num_moved > 0);
|
||||||
WriteBuffer(ToBuf);
|
WriteBuffer(cur_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nmoved > 0)
|
if (num_moved > 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1198,11 +1199,11 @@ failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)",
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clean uncleaned reapped pages from Vvpl list and set xmin committed
|
* Clean uncleaned reapped pages from vacuum_pages list and set xmin committed
|
||||||
* for inserted tuples
|
* for inserted tuples
|
||||||
*/
|
*/
|
||||||
checked_moved = 0;
|
checked_moved = 0;
|
||||||
for (i = 0, vpp = Vvpl->vpl_pagedesc; i < Vnum_pages; i++, vpp++)
|
for (i = 0, vpp = vacuum_pages->vpl_pagedesc; i < vacuumed_pages; i++, vpp++)
|
||||||
{
|
{
|
||||||
Assert((*vpp)->vpd_blkno < blkno);
|
Assert((*vpp)->vpd_blkno < blkno);
|
||||||
buf = ReadBuffer(onerel, (*vpp)->vpd_blkno);
|
buf = ReadBuffer(onerel, (*vpp)->vpd_blkno);
|
||||||
@ -1241,14 +1242,14 @@ failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)",
|
|||||||
}
|
}
|
||||||
WriteBuffer(buf);
|
WriteBuffer(buf);
|
||||||
}
|
}
|
||||||
Assert(nmoved == checked_moved);
|
Assert(num_moved == checked_moved);
|
||||||
|
|
||||||
getrusage(RUSAGE_SELF, &ru1);
|
getrusage(RUSAGE_SELF, &ru1);
|
||||||
|
|
||||||
elog(MESSAGE_LEVEL, "Rel %s: Pages: %u --> %u; Tuple(s) moved: %u. \
|
elog(MESSAGE_LEVEL, "Rel %s: Pages: %u --> %u; Tuple(s) moved: %u. \
|
||||||
Elapsed %u/%u sec.",
|
Elapsed %u/%u sec.",
|
||||||
(RelationGetRelationName(onerel))->data,
|
(RelationGetRelationName(onerel))->data,
|
||||||
nblocks, blkno, nmoved,
|
nblocks, blkno, num_moved,
|
||||||
ru1.ru_stime.tv_sec - ru0.ru_stime.tv_sec,
|
ru1.ru_stime.tv_sec - ru0.ru_stime.tv_sec,
|
||||||
ru1.ru_utime.tv_sec - ru0.ru_utime.tv_sec);
|
ru1.ru_utime.tv_sec - ru0.ru_utime.tv_sec);
|
||||||
|
|
||||||
@ -1339,7 +1340,7 @@ Elapsed %u/%u sec.",
|
|||||||
* if there are "empty" end-blocks.
|
* if there are "empty" end-blocks.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
vc_vacheap(VRelStats *vacrelstats, Relation onerel, VPageList Vvpl)
|
vc_vacheap(VRelStats *vacrelstats, Relation onerel, VPageList vacuum_pages)
|
||||||
{
|
{
|
||||||
Buffer buf;
|
Buffer buf;
|
||||||
Page page;
|
Page page;
|
||||||
@ -1347,10 +1348,10 @@ vc_vacheap(VRelStats *vacrelstats, Relation onerel, VPageList Vvpl)
|
|||||||
int nblocks;
|
int nblocks;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
nblocks = Vvpl->vpl_num_pages;
|
nblocks = vacuum_pages->vpl_num_pages;
|
||||||
nblocks -= Vvpl->vpl_empty_end_pages;/* nothing to do with them */
|
nblocks -= vacuum_pages->vpl_empty_end_pages;/* nothing to do with them */
|
||||||
|
|
||||||
for (i = 0, vpp = Vvpl->vpl_pagedesc; i < nblocks; i++, vpp++)
|
for (i = 0, vpp = vacuum_pages->vpl_pagedesc; i < nblocks; i++, vpp++)
|
||||||
{
|
{
|
||||||
if ((*vpp)->vpd_offsets_free > 0)
|
if ((*vpp)->vpd_offsets_free > 0)
|
||||||
{
|
{
|
||||||
@ -1362,10 +1363,10 @@ vc_vacheap(VRelStats *vacrelstats, Relation onerel, VPageList Vvpl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* truncate relation if there are some empty end-pages */
|
/* truncate relation if there are some empty end-pages */
|
||||||
if (Vvpl->vpl_empty_end_pages > 0)
|
if (vacuum_pages->vpl_empty_end_pages > 0)
|
||||||
{
|
{
|
||||||
Assert(vacrelstats->num_pages >= Vvpl->vpl_empty_end_pages);
|
Assert(vacrelstats->num_pages >= vacuum_pages->vpl_empty_end_pages);
|
||||||
nblocks = vacrelstats->num_pages - Vvpl->vpl_empty_end_pages;
|
nblocks = vacrelstats->num_pages - vacuum_pages->vpl_empty_end_pages;
|
||||||
elog(MESSAGE_LEVEL, "Rel %s: Pages: %u --> %u.",
|
elog(MESSAGE_LEVEL, "Rel %s: Pages: %u --> %u.",
|
||||||
(RelationGetRelationName(onerel))->data,
|
(RelationGetRelationName(onerel))->data,
|
||||||
vacrelstats->num_pages, nblocks);
|
vacrelstats->num_pages, nblocks);
|
||||||
@ -1412,7 +1413,7 @@ vc_vacpage(Page page, VPageDescr vpd)
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
vc_scanoneind(Relation indrel, int nhtups)
|
vc_scanoneind(Relation indrel, int num_tuples)
|
||||||
{
|
{
|
||||||
RetrieveIndexResult res;
|
RetrieveIndexResult res;
|
||||||
IndexScanDesc iscan;
|
IndexScanDesc iscan;
|
||||||
@ -1447,9 +1448,9 @@ vc_scanoneind(Relation indrel, int nhtups)
|
|||||||
ru1.ru_stime.tv_sec - ru0.ru_stime.tv_sec,
|
ru1.ru_stime.tv_sec - ru0.ru_stime.tv_sec,
|
||||||
ru1.ru_utime.tv_sec - ru0.ru_utime.tv_sec);
|
ru1.ru_utime.tv_sec - ru0.ru_utime.tv_sec);
|
||||||
|
|
||||||
if (nitups != nhtups)
|
if (nitups != num_tuples)
|
||||||
elog(NOTICE, "Ind %s: NUMBER OF INDEX' TUPLES (%u) IS NOT THE SAME AS HEAP' (%u)",
|
elog(NOTICE, "Ind %s: NUMBER OF INDEX' TUPLES (%u) IS NOT THE SAME AS HEAP' (%u)",
|
||||||
indrel->rd_rel->relname.data, nitups, nhtups);
|
indrel->rd_rel->relname.data, nitups, num_tuples);
|
||||||
|
|
||||||
} /* vc_scanoneind */
|
} /* vc_scanoneind */
|
||||||
|
|
||||||
@ -1466,14 +1467,14 @@ vc_scanoneind(Relation indrel, int nhtups)
|
|||||||
* pg_class.
|
* pg_class.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
vc_vaconeind(VPageList vpl, Relation indrel, int nhtups)
|
vc_vaconeind(VPageList vpl, Relation indrel, int num_tuples)
|
||||||
{
|
{
|
||||||
RetrieveIndexResult res;
|
RetrieveIndexResult res;
|
||||||
IndexScanDesc iscan;
|
IndexScanDesc iscan;
|
||||||
ItemPointer heapptr;
|
ItemPointer heapptr;
|
||||||
int tups_vacuumed;
|
int tups_vacuumed;
|
||||||
int nitups;
|
int num_index_tuples;
|
||||||
int nipages;
|
int num_pages;
|
||||||
VPageDescr vp;
|
VPageDescr vp;
|
||||||
struct rusage ru0,
|
struct rusage ru0,
|
||||||
ru1;
|
ru1;
|
||||||
@ -1483,7 +1484,7 @@ vc_vaconeind(VPageList vpl, Relation indrel, int nhtups)
|
|||||||
/* walk through the entire index */
|
/* walk through the entire index */
|
||||||
iscan = index_beginscan(indrel, false, 0, (ScanKey) NULL);
|
iscan = index_beginscan(indrel, false, 0, (ScanKey) NULL);
|
||||||
tups_vacuumed = 0;
|
tups_vacuumed = 0;
|
||||||
nitups = 0;
|
num_index_tuples = 0;
|
||||||
|
|
||||||
while ((res = index_getnext(iscan, ForwardScanDirection))
|
while ((res = index_getnext(iscan, ForwardScanDirection))
|
||||||
!= (RetrieveIndexResult) NULL)
|
!= (RetrieveIndexResult) NULL)
|
||||||
@ -1509,7 +1510,7 @@ vc_vaconeind(VPageList vpl, Relation indrel, int nhtups)
|
|||||||
index_delete(indrel, &res->index_iptr);
|
index_delete(indrel, &res->index_iptr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
nitups++;
|
num_index_tuples++;
|
||||||
|
|
||||||
pfree(res);
|
pfree(res);
|
||||||
}
|
}
|
||||||
@ -1517,19 +1518,19 @@ vc_vaconeind(VPageList vpl, Relation indrel, int nhtups)
|
|||||||
index_endscan(iscan);
|
index_endscan(iscan);
|
||||||
|
|
||||||
/* now update statistics in pg_class */
|
/* now update statistics in pg_class */
|
||||||
nipages = RelationGetNumberOfBlocks(indrel);
|
num_pages = RelationGetNumberOfBlocks(indrel);
|
||||||
vc_updstats(RelationGetRelid(indrel), nipages, nitups, false, NULL);
|
vc_updstats(RelationGetRelid(indrel), num_pages, num_index_tuples, false, NULL);
|
||||||
|
|
||||||
getrusage(RUSAGE_SELF, &ru1);
|
getrusage(RUSAGE_SELF, &ru1);
|
||||||
|
|
||||||
elog(MESSAGE_LEVEL, "Ind %s: Pages %u; Tuples %u: Deleted %u. Elapsed %u/%u sec.",
|
elog(MESSAGE_LEVEL, "Ind %s: Pages %u; Tuples %u: Deleted %u. Elapsed %u/%u sec.",
|
||||||
indrel->rd_rel->relname.data, nipages, nitups, tups_vacuumed,
|
indrel->rd_rel->relname.data, num_pages, num_index_tuples, tups_vacuumed,
|
||||||
ru1.ru_stime.tv_sec - ru0.ru_stime.tv_sec,
|
ru1.ru_stime.tv_sec - ru0.ru_stime.tv_sec,
|
||||||
ru1.ru_utime.tv_sec - ru0.ru_utime.tv_sec);
|
ru1.ru_utime.tv_sec - ru0.ru_utime.tv_sec);
|
||||||
|
|
||||||
if (nitups != nhtups)
|
if (num_index_tuples != num_tuples)
|
||||||
elog(NOTICE, "Ind %s: NUMBER OF INDEX' TUPLES (%u) IS NOT THE SAME AS HEAP' (%u)",
|
elog(NOTICE, "Ind %s: NUMBER OF INDEX' TUPLES (%u) IS NOT THE SAME AS HEAP' (%u)",
|
||||||
indrel->rd_rel->relname.data, nitups, nhtups);
|
indrel->rd_rel->relname.data, num_index_tuples, num_tuples);
|
||||||
|
|
||||||
} /* vc_vaconeind */
|
} /* vc_vaconeind */
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user