mirror of
https://github.com/postgres/postgres.git
synced 2025-05-21 00:02:53 -04:00
Allow vacuum to perform analyze with shared lock. Update cvs manual.
This commit is contained in:
parent
091126fa28
commit
659f79be7a
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
$Header: /cvsroot/pgsql/doc/src/sgml/cvs.sgml,v 1.8 2000/05/02 20:01:51 thomas Exp $
|
$Header: /cvsroot/pgsql/doc/src/sgml/cvs.sgml,v 1.9 2000/05/29 15:44:54 momjian Exp $
|
||||||
CVS code repository
|
CVS code repository
|
||||||
Thomas Lockhart
|
Thomas Lockhart
|
||||||
-->
|
-->
|
||||||
@ -184,7 +184,7 @@ cvs commit
|
|||||||
Do an initial login to the <productname>CVS</productname> server:
|
Do an initial login to the <productname>CVS</productname> server:
|
||||||
|
|
||||||
<programlisting>
|
<programlisting>
|
||||||
$ cvs -d :pserver:anoncvs@postgresql.org:/usr/local/cvsroot login
|
$ cvs -d :pserver:anoncvs@postgresql.org:/home/projects/pgsql/cvsroot login
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
|
||||||
You will be prompted for a password; enter '<literal>postgresql</literal>'.
|
You will be prompted for a password; enter '<literal>postgresql</literal>'.
|
||||||
@ -197,7 +197,7 @@ $ cvs -d :pserver:anoncvs@postgresql.org:/usr/local/cvsroot login
|
|||||||
<para>
|
<para>
|
||||||
Fetch the <productname>Postgres</productname> sources:
|
Fetch the <productname>Postgres</productname> sources:
|
||||||
<programlisting>
|
<programlisting>
|
||||||
cvs -z3 -d :pserver:anoncvs@postgresql.org:/usr/local/cvsroot co -P pgsql
|
cvs -z3 -d :pserver:anoncvs@postgresql.org:/home/projects/pgsql/cvsroot co -P pgsql
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
|
||||||
which installs the <productname>Postgres</productname> sources into a
|
which installs the <productname>Postgres</productname> sources into a
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.151 2000/05/29 01:55:07 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.152 2000/05/29 15:44:55 momjian Exp $
|
||||||
*
|
*
|
||||||
|
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
@ -77,15 +77,17 @@ static void vacuum_shutdown(void);
|
|||||||
static void vac_vacuum(NameData *VacRelP, bool analyze, List *va_cols);
|
static void vac_vacuum(NameData *VacRelP, bool analyze, List *va_cols);
|
||||||
static VRelList getrels(NameData *VacRelP);
|
static VRelList getrels(NameData *VacRelP);
|
||||||
static void vacuum_rel(Oid relid, bool analyze, List *va_cols);
|
static void vacuum_rel(Oid relid, bool analyze, List *va_cols);
|
||||||
|
static void analyze_rel(Oid relid, List *va_cols);
|
||||||
static void scan_heap(VRelStats *vacrelstats, Relation onerel, VPageList vacuum_pages, VPageList fraged_pages);
|
static void scan_heap(VRelStats *vacrelstats, Relation onerel, VPageList vacuum_pages, VPageList fraged_pages);
|
||||||
static void repair_frag(VRelStats *vacrelstats, Relation onerel, VPageList vacuum_pages, VPageList fraged_pages, int nindices, Relation *Irel);
|
static void repair_frag(VRelStats *vacrelstats, Relation onerel, VPageList vacuum_pages, VPageList fraged_pages, int nindices, Relation *Irel);
|
||||||
static void vacuum_heap(VRelStats *vacrelstats, Relation onerel, VPageList vpl);
|
static void vacuum_heap(VRelStats *vacrelstats, Relation onerel, VPageList vpl);
|
||||||
static void vacuum_page(Page page, VPageDescr vpd);
|
static void vacuum_page(Page page, VPageDescr vpd);
|
||||||
static void vacuum_index(VPageList vpl, Relation indrel, int num_tuples, int keep_tuples);
|
static void vacuum_index(VPageList vpl, Relation indrel, int num_tuples, int keep_tuples);
|
||||||
static void scan_index(Relation indrel, int num_tuples);
|
static void scan_index(Relation indrel, int num_tuples);
|
||||||
static void attr_stats(Relation onerel, VRelStats *vacrelstats, HeapTuple tuple);
|
static void attr_stats(Relation onerel, int attr_cnt, VacAttrStats *vacattrstats, HeapTuple tuple);
|
||||||
static void bucketcpy(Form_pg_attribute attr, Datum value, Datum *bucket, int *bucket_len);
|
static void bucketcpy(Form_pg_attribute attr, Datum value, Datum *bucket, int *bucket_len);
|
||||||
static void update_stats(Oid relid, int num_pages, int num_tuples, bool hasindex, VRelStats *vacrelstats);
|
static void update_relstats(Oid relid, int num_pages, int num_tuples, bool hasindex, VRelStats *vacrelstats);
|
||||||
|
static void update_attstats(Oid relid, int natts, VacAttrStats *vacattrstats);
|
||||||
static void del_stats(Oid relid, int attcnt, int *attnums);
|
static void del_stats(Oid relid, int attcnt, int *attnums);
|
||||||
static VPageDescr tid_reaped(ItemPointer itemptr, VPageList vpl);
|
static VPageDescr tid_reaped(ItemPointer itemptr, VPageList vpl);
|
||||||
static void reap_page(VPageList vpl, VPageDescr vpc);
|
static void reap_page(VPageList vpl, VPageDescr vpc);
|
||||||
@ -100,63 +102,7 @@ static int vac_cmp_offno(const void *left, const void *right);
|
|||||||
static int vac_cmp_vtlinks(const void *left, const void *right);
|
static int vac_cmp_vtlinks(const void *left, const void *right);
|
||||||
static bool enough_space(VPageDescr vpd, Size len);
|
static bool enough_space(VPageDescr vpd, Size len);
|
||||||
static char *show_rusage(struct rusage * ru0);
|
static char *show_rusage(struct rusage * ru0);
|
||||||
|
/* CommonSpecialPortal function at the bottom */
|
||||||
|
|
||||||
/*
|
|
||||||
* This routines handle a special cross-transaction portal.
|
|
||||||
* However it is automatically closed in case of abort.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
CommonSpecialPortalOpen(void)
|
|
||||||
{
|
|
||||||
char *pname;
|
|
||||||
|
|
||||||
|
|
||||||
if (CommonSpecialPortalInUse)
|
|
||||||
elog(ERROR, "CommonSpecialPortal is in use");
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create a portal for safe memory across transactions. We need to
|
|
||||||
* palloc the name space for it because our hash function expects the
|
|
||||||
* name to be on a longword boundary. CreatePortal copies the name to
|
|
||||||
* safe storage for us.
|
|
||||||
*/
|
|
||||||
pname = pstrdup(VACPNAME);
|
|
||||||
vac_portal = CreatePortal(pname);
|
|
||||||
pfree(pname);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set flag to indicate that vac_portal must be removed after an error.
|
|
||||||
* This global variable is checked in the transaction manager on xact
|
|
||||||
* abort, and the routine CommonSpecialPortalClose() is called if
|
|
||||||
* necessary.
|
|
||||||
*/
|
|
||||||
CommonSpecialPortalInUse = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CommonSpecialPortalClose(void)
|
|
||||||
{
|
|
||||||
/* Clear flag first, to avoid recursion if PortalDrop elog's */
|
|
||||||
CommonSpecialPortalInUse = false;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Release our portal for cross-transaction memory.
|
|
||||||
*/
|
|
||||||
PortalDrop(&vac_portal);
|
|
||||||
}
|
|
||||||
|
|
||||||
PortalVariableMemory
|
|
||||||
CommonSpecialPortalGetMemory(void)
|
|
||||||
{
|
|
||||||
return PortalGetVariableMemory(vac_portal);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
CommonSpecialPortalIsOpen(void)
|
|
||||||
{
|
|
||||||
return CommonSpecialPortalInUse;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
vacuum(char *vacrel, bool verbose, bool analyze, List *va_spec)
|
vacuum(char *vacrel, bool verbose, bool analyze, List *va_spec)
|
||||||
@ -299,6 +245,11 @@ vac_vacuum(NameData *VacRelP, bool analyze, List *va_cols)
|
|||||||
/* vacuum each heap relation */
|
/* vacuum each heap relation */
|
||||||
for (cur = vrl; cur != (VRelList) NULL; cur = cur->vrl_next)
|
for (cur = vrl; cur != (VRelList) NULL; cur = cur->vrl_next)
|
||||||
vacuum_rel(cur->vrl_relid, analyze, va_cols);
|
vacuum_rel(cur->vrl_relid, analyze, va_cols);
|
||||||
|
|
||||||
|
/* analyze separately so locking is minimized */
|
||||||
|
if (analyze)
|
||||||
|
for (cur = vrl; cur != (VRelList) NULL; cur = cur->vrl_next)
|
||||||
|
analyze_rel(cur->vrl_relid, va_cols);
|
||||||
}
|
}
|
||||||
|
|
||||||
static VRelList
|
static VRelList
|
||||||
@ -410,8 +361,7 @@ getrels(NameData *VacRelP)
|
|||||||
static void
|
static void
|
||||||
vacuum_rel(Oid relid, bool analyze, List *va_cols)
|
vacuum_rel(Oid relid, bool analyze, List *va_cols)
|
||||||
{
|
{
|
||||||
HeapTuple tuple,
|
HeapTuple tuple;
|
||||||
typetuple;
|
|
||||||
Relation onerel;
|
Relation onerel;
|
||||||
VPageListData vacuum_pages; /* List of pages to vacuum and/or clean
|
VPageListData vacuum_pages; /* List of pages to vacuum and/or clean
|
||||||
* indices */
|
* indices */
|
||||||
@ -474,16 +424,151 @@ vacuum_rel(Oid relid, bool analyze, List *va_cols)
|
|||||||
vacrelstats->num_pages = vacrelstats->num_tuples = 0;
|
vacrelstats->num_pages = vacrelstats->num_tuples = 0;
|
||||||
vacrelstats->hasindex = false;
|
vacrelstats->hasindex = false;
|
||||||
|
|
||||||
/*
|
GetXmaxRecent(&XmaxRecent);
|
||||||
* we can VACUUM ANALYZE any table except pg_statistic; see
|
|
||||||
* update_stats
|
/* scan it */
|
||||||
*/
|
reindex = false;
|
||||||
if (analyze &&
|
vacuum_pages.vpl_num_pages = fraged_pages.vpl_num_pages = 0;
|
||||||
strcmp(RelationGetRelationName(onerel), StatisticRelationName) != 0)
|
scan_heap(vacrelstats, onerel, &vacuum_pages, &fraged_pages);
|
||||||
|
if (IsIgnoringSystemIndexes() && IsSystemRelationName(RelationGetRelationName(onerel)))
|
||||||
|
reindex = true;
|
||||||
|
|
||||||
|
/* Now open indices */
|
||||||
|
nindices = 0;
|
||||||
|
Irel = (Relation *) NULL;
|
||||||
|
get_indices(vacrelstats->relid, &nindices, &Irel);
|
||||||
|
if (!Irel)
|
||||||
|
reindex = false;
|
||||||
|
else if (!RelationGetForm(onerel)->relhasindex)
|
||||||
|
reindex = true;
|
||||||
|
if (nindices > 0)
|
||||||
|
vacrelstats->hasindex = true;
|
||||||
|
else
|
||||||
|
vacrelstats->hasindex = false;
|
||||||
|
if (reindex)
|
||||||
{
|
{
|
||||||
|
for (i = 0; i < nindices; i++)
|
||||||
|
index_close(Irel[i]);
|
||||||
|
Irel = (Relation *) NULL;
|
||||||
|
activate_indexes_of_a_table(relid, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clean/scan index relation(s) */
|
||||||
|
if (Irel != (Relation *) NULL)
|
||||||
|
{
|
||||||
|
if (vacuum_pages.vpl_num_pages > 0)
|
||||||
|
{
|
||||||
|
for (i = 0; i < nindices; i++)
|
||||||
|
vacuum_index(&vacuum_pages, Irel[i], vacrelstats->num_tuples, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* just scan indices to update statistic */
|
||||||
|
{
|
||||||
|
for (i = 0; i < nindices; i++)
|
||||||
|
scan_index(Irel[i], vacrelstats->num_tuples);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fraged_pages.vpl_num_pages > 0) /* Try to shrink heap */
|
||||||
|
repair_frag(vacrelstats, onerel, &vacuum_pages, &fraged_pages, nindices, Irel);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Irel != (Relation *) NULL)
|
||||||
|
close_indices(nindices, Irel);
|
||||||
|
if (vacuum_pages.vpl_num_pages > 0) /* Clean pages from
|
||||||
|
* vacuum_pages list */
|
||||||
|
vacuum_heap(vacrelstats, onerel, &vacuum_pages);
|
||||||
|
}
|
||||||
|
if (reindex)
|
||||||
|
activate_indexes_of_a_table(relid, true);
|
||||||
|
|
||||||
|
/* ok - free vacuum_pages list of reaped pages */
|
||||||
|
if (vacuum_pages.vpl_num_pages > 0)
|
||||||
|
{
|
||||||
|
vpp = vacuum_pages.vpl_pagedesc;
|
||||||
|
for (i = 0; i < vacuum_pages.vpl_num_pages; i++, vpp++)
|
||||||
|
pfree(*vpp);
|
||||||
|
pfree(vacuum_pages.vpl_pagedesc);
|
||||||
|
if (fraged_pages.vpl_num_pages > 0)
|
||||||
|
pfree(fraged_pages.vpl_pagedesc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* all done with this class, but hold lock until commit */
|
||||||
|
heap_close(onerel, NoLock);
|
||||||
|
|
||||||
|
/* update statistics in pg_class */
|
||||||
|
update_relstats(vacrelstats->relid, vacrelstats->num_pages,
|
||||||
|
vacrelstats->num_tuples, vacrelstats->hasindex, vacrelstats);
|
||||||
|
|
||||||
|
/* next command frees attribute stats */
|
||||||
|
CommitTransactionCommand();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* analyze_rel() -- analyze relation
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
analyze_rel(Oid relid, List *va_cols)
|
||||||
|
{
|
||||||
|
HeapTuple tuple,
|
||||||
|
typetuple;
|
||||||
|
Relation onerel;
|
||||||
|
int32 i;
|
||||||
int attr_cnt,
|
int attr_cnt,
|
||||||
*attnums = NULL;
|
*attnums = NULL;
|
||||||
Form_pg_attribute *attr;
|
Form_pg_attribute *attr;
|
||||||
|
VacAttrStats *vacattrstats;
|
||||||
|
HeapScanDesc scan;
|
||||||
|
|
||||||
|
StartTransactionCommand();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for user-requested abort. Note we want this to be inside a
|
||||||
|
* transaction, so xact.c doesn't issue useless NOTICE.
|
||||||
|
*/
|
||||||
|
if (QueryCancel)
|
||||||
|
CancelQuery();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Race condition -- if the pg_class tuple has gone away since the
|
||||||
|
* last time we saw it, we don't need to vacuum it.
|
||||||
|
*/
|
||||||
|
tuple = SearchSysCacheTuple(RELOID,
|
||||||
|
ObjectIdGetDatum(relid),
|
||||||
|
0, 0, 0);
|
||||||
|
/*
|
||||||
|
* We can VACUUM ANALYZE any table except pg_statistic.
|
||||||
|
* see update_relstats
|
||||||
|
*/
|
||||||
|
if (!HeapTupleIsValid(tuple) ||
|
||||||
|
strcmp(NameStr(((Form_pg_class) GETSTRUCT(tuple))->relname),
|
||||||
|
StatisticRelationName) == 0)
|
||||||
|
{
|
||||||
|
CommitTransactionCommand();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Open the class, get an exclusive lock on it, and check permissions.
|
||||||
|
*
|
||||||
|
* Note we choose to treat permissions failure as a NOTICE and keep
|
||||||
|
* trying to vacuum the rest of the DB --- is this appropriate?
|
||||||
|
*/
|
||||||
|
onerel = heap_open(relid, AccessShareLock);
|
||||||
|
|
||||||
|
#ifndef NO_SECURITY
|
||||||
|
if (!pg_ownercheck(GetPgUserName(), RelationGetRelationName(onerel),
|
||||||
|
RELNAME))
|
||||||
|
{
|
||||||
|
/* we already did an elog during vacuum
|
||||||
|
elog(NOTICE, "Skipping \"%s\" --- only table owner can VACUUM it",
|
||||||
|
RelationGetRelationName(onerel));
|
||||||
|
*/
|
||||||
|
heap_close(onerel, AccessExclusiveLock);
|
||||||
|
CommitTransactionCommand();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
attr_cnt = onerel->rd_att->natts;
|
attr_cnt = onerel->rd_att->natts;
|
||||||
attr = onerel->rd_att->attrs;
|
attr = onerel->rd_att->attrs;
|
||||||
@ -517,7 +602,7 @@ vacuum_rel(Oid relid, bool analyze, List *va_cols)
|
|||||||
attr_cnt = tcnt;
|
attr_cnt = tcnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
vacrelstats->vacattrstats = (VacAttrStats *) palloc(attr_cnt * sizeof(VacAttrStats));
|
vacattrstats = (VacAttrStats *) palloc(attr_cnt * sizeof(VacAttrStats));
|
||||||
|
|
||||||
for (i = 0; i < attr_cnt; i++)
|
for (i = 0; i < attr_cnt; i++)
|
||||||
{
|
{
|
||||||
@ -525,7 +610,7 @@ vacuum_rel(Oid relid, bool analyze, List *va_cols)
|
|||||||
Form_pg_operator pgopform;
|
Form_pg_operator pgopform;
|
||||||
VacAttrStats *stats;
|
VacAttrStats *stats;
|
||||||
|
|
||||||
stats = &vacrelstats->vacattrstats[i];
|
stats = &vacattrstats[i];
|
||||||
stats->attr = palloc(ATTRIBUTE_TUPLE_SIZE);
|
stats->attr = palloc(ATTRIBUTE_TUPLE_SIZE);
|
||||||
memmove(stats->attr, attr[((attnums) ? attnums[i] : i)], ATTRIBUTE_TUPLE_SIZE);
|
memmove(stats->attr, attr[((attnums) ? attnums[i] : i)], ATTRIBUTE_TUPLE_SIZE);
|
||||||
stats->best = stats->guess1 = stats->guess2 = 0;
|
stats->best = stats->guess1 = stats->guess2 = 0;
|
||||||
@ -581,95 +666,21 @@ vacuum_rel(Oid relid, bool analyze, List *va_cols)
|
|||||||
stats->typelem = InvalidOid;
|
stats->typelem = InvalidOid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vacrelstats->va_natts = attr_cnt;
|
|
||||||
/* delete existing pg_statistic rows for relation */
|
/* delete existing pg_statistic rows for relation */
|
||||||
del_stats(relid, ((attnums) ? attr_cnt : 0), attnums);
|
del_stats(relid, ((attnums) ? attr_cnt : 0), attnums);
|
||||||
if (attnums)
|
|
||||||
pfree(attnums);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
vacrelstats->va_natts = 0;
|
|
||||||
vacrelstats->vacattrstats = (VacAttrStats *) NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
GetXmaxRecent(&XmaxRecent);
|
scan = heap_beginscan(onerel, false, SnapshotNow, 0, NULL);
|
||||||
|
|
||||||
/* scan it */
|
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
|
||||||
reindex = false;
|
attr_stats(onerel, attr_cnt, vacattrstats, tuple);
|
||||||
vacuum_pages.vpl_num_pages = fraged_pages.vpl_num_pages = 0;
|
|
||||||
scan_heap(vacrelstats, onerel, &vacuum_pages, &fraged_pages);
|
|
||||||
if (IsIgnoringSystemIndexes() && IsSystemRelationName(RelationGetRelationName(onerel)))
|
|
||||||
reindex = true;
|
|
||||||
|
|
||||||
/* Now open indices */
|
heap_endscan(scan);
|
||||||
nindices = 0;
|
|
||||||
Irel = (Relation *) NULL;
|
|
||||||
get_indices(vacrelstats->relid, &nindices, &Irel);
|
|
||||||
if (!Irel)
|
|
||||||
reindex = false;
|
|
||||||
else if (!RelationGetForm(onerel)->relhasindex)
|
|
||||||
reindex = true;
|
|
||||||
if (nindices > 0)
|
|
||||||
vacrelstats->hasindex = true;
|
|
||||||
else
|
|
||||||
vacrelstats->hasindex = false;
|
|
||||||
if (reindex)
|
|
||||||
{
|
|
||||||
for (i = 0; i < nindices; i++)
|
|
||||||
index_close(Irel[i]);
|
|
||||||
Irel = (Relation *) NULL;
|
|
||||||
activate_indexes_of_a_table(relid, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clean/scan index relation(s) */
|
heap_close(onerel, AccessShareLock);
|
||||||
if (Irel != (Relation *) NULL)
|
|
||||||
{
|
|
||||||
if (vacuum_pages.vpl_num_pages > 0)
|
|
||||||
{
|
|
||||||
for (i = 0; i < nindices; i++)
|
|
||||||
vacuum_index(&vacuum_pages, Irel[i], vacrelstats->num_tuples, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
/* just scan indices to update statistic */
|
|
||||||
{
|
|
||||||
for (i = 0; i < nindices; i++)
|
|
||||||
scan_index(Irel[i], vacrelstats->num_tuples);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fraged_pages.vpl_num_pages > 0) /* Try to shrink heap */
|
|
||||||
repair_frag(vacrelstats, onerel, &vacuum_pages, &fraged_pages, nindices, Irel);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (Irel != (Relation *) NULL)
|
|
||||||
close_indices(nindices, Irel);
|
|
||||||
if (vacuum_pages.vpl_num_pages > 0) /* Clean pages from
|
|
||||||
* vacuum_pages list */
|
|
||||||
vacuum_heap(vacrelstats, onerel, &vacuum_pages);
|
|
||||||
}
|
|
||||||
if (reindex)
|
|
||||||
activate_indexes_of_a_table(relid, true);
|
|
||||||
|
|
||||||
/* ok - free vacuum_pages list of reaped pages */
|
|
||||||
if (vacuum_pages.vpl_num_pages > 0)
|
|
||||||
{
|
|
||||||
vpp = vacuum_pages.vpl_pagedesc;
|
|
||||||
for (i = 0; i < vacuum_pages.vpl_num_pages; i++, vpp++)
|
|
||||||
pfree(*vpp);
|
|
||||||
pfree(vacuum_pages.vpl_pagedesc);
|
|
||||||
if (fraged_pages.vpl_num_pages > 0)
|
|
||||||
pfree(fraged_pages.vpl_pagedesc);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* update statistics in pg_class */
|
/* update statistics in pg_class */
|
||||||
update_stats(vacrelstats->relid, vacrelstats->num_pages,
|
update_attstats(relid, attr_cnt, vacattrstats);
|
||||||
vacrelstats->num_tuples, vacrelstats->hasindex, vacrelstats);
|
|
||||||
|
|
||||||
/* all done with this class, but hold lock until commit */
|
|
||||||
heap_close(onerel, NoLock);
|
|
||||||
|
|
||||||
/* next command frees attribute stats */
|
|
||||||
CommitTransactionCommand();
|
CommitTransactionCommand();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -979,7 +990,6 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
|
|||||||
min_tlen = tuple.t_len;
|
min_tlen = tuple.t_len;
|
||||||
if (tuple.t_len > max_tlen)
|
if (tuple.t_len > max_tlen)
|
||||||
max_tlen = tuple.t_len;
|
max_tlen = tuple.t_len;
|
||||||
attr_stats(onerel, vacrelstats, &tuple);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2106,7 +2116,7 @@ scan_index(Relation indrel, int num_tuples)
|
|||||||
|
|
||||||
/* now update statistics in pg_class */
|
/* now update statistics in pg_class */
|
||||||
nipages = RelationGetNumberOfBlocks(indrel);
|
nipages = RelationGetNumberOfBlocks(indrel);
|
||||||
update_stats(RelationGetRelid(indrel), nipages, nitups, false, NULL);
|
update_relstats(RelationGetRelid(indrel), nipages, nitups, false, NULL);
|
||||||
|
|
||||||
elog(MESSAGE_LEVEL, "Index %s: Pages %u; Tuples %u. %s",
|
elog(MESSAGE_LEVEL, "Index %s: Pages %u; Tuples %u. %s",
|
||||||
RelationGetRelationName(indrel), nipages, nitups,
|
RelationGetRelationName(indrel), nipages, nitups,
|
||||||
@ -2183,7 +2193,7 @@ vacuum_index(VPageList vpl, Relation indrel, int num_tuples, int keep_tuples)
|
|||||||
|
|
||||||
/* now update statistics in pg_class */
|
/* now update statistics in pg_class */
|
||||||
num_pages = RelationGetNumberOfBlocks(indrel);
|
num_pages = RelationGetNumberOfBlocks(indrel);
|
||||||
update_stats(RelationGetRelid(indrel), num_pages, num_index_tuples, false, NULL);
|
update_relstats(RelationGetRelid(indrel), num_pages, num_index_tuples, false, NULL);
|
||||||
|
|
||||||
elog(MESSAGE_LEVEL, "Index %s: Pages %u; Tuples %u: Deleted %u. %s",
|
elog(MESSAGE_LEVEL, "Index %s: Pages %u; Tuples %u: Deleted %u. %s",
|
||||||
RelationGetRelationName(indrel), num_pages,
|
RelationGetRelationName(indrel), num_pages,
|
||||||
@ -2263,11 +2273,9 @@ tid_reaped(ItemPointer itemptr, VPageList vpl)
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
attr_stats(Relation onerel, VRelStats *vacrelstats, HeapTuple tuple)
|
attr_stats(Relation onerel, int attr_cnt, VacAttrStats *vacattrstats, HeapTuple tuple)
|
||||||
{
|
{
|
||||||
int i,
|
int i;
|
||||||
attr_cnt = vacrelstats->va_natts;
|
|
||||||
VacAttrStats *vacattrstats = vacrelstats->vacattrstats;
|
|
||||||
TupleDesc tupDesc = onerel->rd_att;
|
TupleDesc tupDesc = onerel->rd_att;
|
||||||
Datum value;
|
Datum value;
|
||||||
bool isnull;
|
bool isnull;
|
||||||
@ -2387,7 +2395,7 @@ bucketcpy(Form_pg_attribute attr, Datum value, Datum *bucket, int *bucket_len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* update_stats() -- update statistics for one relation
|
* update_relstats() -- update statistics for one relation
|
||||||
*
|
*
|
||||||
* Statistics are stored in several places: the pg_class row for the
|
* Statistics are stored in several places: the pg_class row for the
|
||||||
* relation has stats about the whole relation, the pg_attribute rows
|
* relation has stats about the whole relation, the pg_attribute rows
|
||||||
@ -2408,29 +2416,15 @@ bucketcpy(Form_pg_attribute attr, Datum value, Datum *bucket, int *bucket_len)
|
|||||||
* Updating pg_class's own statistics would be especially tricky.
|
* Updating pg_class's own statistics would be especially tricky.
|
||||||
* Of course, this only works for fixed-size never-null columns, but
|
* Of course, this only works for fixed-size never-null columns, but
|
||||||
* these are.
|
* these are.
|
||||||
*
|
|
||||||
* Updates of pg_attribute statistics are handled in the same way
|
|
||||||
* for the same reasons.
|
|
||||||
*
|
|
||||||
* To keep things simple, we punt for pg_statistic, and don't try
|
|
||||||
* to compute or store rows for pg_statistic itself in pg_statistic.
|
|
||||||
* This could possibly be made to work, but it's not worth the trouble.
|
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
update_stats(Oid relid, int num_pages, int num_tuples, bool hasindex,
|
update_relstats(Oid relid, int num_pages, int num_tuples, bool hasindex,
|
||||||
VRelStats *vacrelstats)
|
VRelStats *vacrelstats)
|
||||||
{
|
{
|
||||||
Relation rd,
|
Relation rd;
|
||||||
ad,
|
|
||||||
sd;
|
|
||||||
HeapScanDesc scan;
|
|
||||||
HeapTupleData rtup;
|
HeapTupleData rtup;
|
||||||
HeapTuple ctup,
|
HeapTuple ctup;
|
||||||
atup,
|
|
||||||
stup;
|
|
||||||
Form_pg_class pgcform;
|
Form_pg_class pgcform;
|
||||||
ScanKeyData askey;
|
|
||||||
Form_pg_attribute attp;
|
|
||||||
Buffer buffer;
|
Buffer buffer;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2461,11 +2455,28 @@ update_stats(Oid relid, int num_pages, int num_tuples, bool hasindex,
|
|||||||
WriteBuffer(buffer);
|
WriteBuffer(buffer);
|
||||||
|
|
||||||
heap_close(rd, RowExclusiveLock);
|
heap_close(rd, RowExclusiveLock);
|
||||||
|
}
|
||||||
|
|
||||||
if (vacrelstats != NULL && vacrelstats->va_natts > 0)
|
/*
|
||||||
{
|
* update_attstats() -- update attribute statistics for one relation
|
||||||
VacAttrStats *vacattrstats = vacrelstats->vacattrstats;
|
*
|
||||||
int natts = vacrelstats->va_natts;
|
* Updates of pg_attribute statistics are handled by over-write.
|
||||||
|
* for reasons described above.
|
||||||
|
*
|
||||||
|
* To keep things simple, we punt for pg_statistic, and don't try
|
||||||
|
* to compute or store rows for pg_statistic itself in pg_statistic.
|
||||||
|
* This could possibly be made to work, but it's not worth the trouble.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
update_attstats(Oid relid, int natts, VacAttrStats *vacattrstats)
|
||||||
|
{
|
||||||
|
Relation ad,
|
||||||
|
sd;
|
||||||
|
HeapScanDesc scan;
|
||||||
|
HeapTuple atup,
|
||||||
|
stup;
|
||||||
|
ScanKeyData askey;
|
||||||
|
Form_pg_attribute attp;
|
||||||
|
|
||||||
ad = heap_openr(AttributeRelationName, RowExclusiveLock);
|
ad = heap_openr(AttributeRelationName, RowExclusiveLock);
|
||||||
sd = heap_openr(StatisticRelationName, RowExclusiveLock);
|
sd = heap_openr(StatisticRelationName, RowExclusiveLock);
|
||||||
@ -2511,7 +2522,6 @@ update_stats(Oid relid, int num_pages, int num_tuples, bool hasindex,
|
|||||||
}
|
}
|
||||||
else if (stats->null_cnt <= 1 && stats->best_cnt == 1)
|
else if (stats->null_cnt <= 1 && stats->best_cnt == 1)
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* looks like we have a unique-key attribute --- flag
|
* looks like we have a unique-key attribute --- flag
|
||||||
* this with special -1.0 flag value.
|
* this with special -1.0 flag value.
|
||||||
@ -2656,7 +2666,6 @@ update_stats(Oid relid, int num_pages, int num_tuples, bool hasindex,
|
|||||||
/* close rels, but hold locks till upcoming commit */
|
/* close rels, but hold locks till upcoming commit */
|
||||||
heap_close(ad, NoLock);
|
heap_close(ad, NoLock);
|
||||||
heap_close(sd, NoLock);
|
heap_close(sd, NoLock);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2867,6 +2876,62 @@ vac_cmp_vtlinks(const void *left, const void *right)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This routines handle a special cross-transaction portal.
|
||||||
|
* However it is automatically closed in case of abort.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
CommonSpecialPortalOpen(void)
|
||||||
|
{
|
||||||
|
char *pname;
|
||||||
|
|
||||||
|
|
||||||
|
if (CommonSpecialPortalInUse)
|
||||||
|
elog(ERROR, "CommonSpecialPortal is in use");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a portal for safe memory across transactions. We need to
|
||||||
|
* palloc the name space for it because our hash function expects the
|
||||||
|
* name to be on a longword boundary. CreatePortal copies the name to
|
||||||
|
* safe storage for us.
|
||||||
|
*/
|
||||||
|
pname = pstrdup(VACPNAME);
|
||||||
|
vac_portal = CreatePortal(pname);
|
||||||
|
pfree(pname);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set flag to indicate that vac_portal must be removed after an error.
|
||||||
|
* This global variable is checked in the transaction manager on xact
|
||||||
|
* abort, and the routine CommonSpecialPortalClose() is called if
|
||||||
|
* necessary.
|
||||||
|
*/
|
||||||
|
CommonSpecialPortalInUse = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CommonSpecialPortalClose(void)
|
||||||
|
{
|
||||||
|
/* Clear flag first, to avoid recursion if PortalDrop elog's */
|
||||||
|
CommonSpecialPortalInUse = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Release our portal for cross-transaction memory.
|
||||||
|
*/
|
||||||
|
PortalDrop(&vac_portal);
|
||||||
|
}
|
||||||
|
|
||||||
|
PortalVariableMemory
|
||||||
|
CommonSpecialPortalGetMemory(void)
|
||||||
|
{
|
||||||
|
return PortalGetVariableMemory(vac_portal);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CommonSpecialPortalIsOpen(void)
|
||||||
|
{
|
||||||
|
return CommonSpecialPortalInUse;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
get_indices(Oid relid, int *nindices, Relation **Irel)
|
get_indices(Oid relid, int *nindices, Relation **Irel)
|
||||||
{
|
{
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: vacuum.h,v 1.27 2000/04/12 17:16:32 momjian Exp $
|
* $Id: vacuum.h,v 1.28 2000/05/29 15:44:55 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -125,8 +125,6 @@ typedef struct VRelStats
|
|||||||
Size min_tlen;
|
Size min_tlen;
|
||||||
Size max_tlen;
|
Size max_tlen;
|
||||||
bool hasindex;
|
bool hasindex;
|
||||||
int va_natts; /* number of attrs being analyzed */
|
|
||||||
VacAttrStats *vacattrstats;
|
|
||||||
int num_vtlinks;
|
int num_vtlinks;
|
||||||
VTupleLink vtlinks;
|
VTupleLink vtlinks;
|
||||||
} VRelStats;
|
} VRelStats;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user