mirror of
https://github.com/postgres/postgres.git
synced 2025-04-27 22:56:53 +03:00
Allow multiple tables to be specified in one VACUUM or ANALYZE command.
Not much to say about this; does what it says on the tin. However, formerly, if there was a column list then the ANALYZE action was implied; now it must be specified, or you get an error. This is because it would otherwise be a bit unclear what the user meant if some tables have column lists and some don't. Nathan Bossart, reviewed by Michael Paquier and Masahiko Sawada, with some editorialization by me Discussion: https://postgr.es/m/E061A8E3-5E3D-494D-94F0-E8A9B312BBFC@amazon.com
This commit is contained in:
parent
45f9d08684
commit
11d8d72c27
@ -21,7 +21,11 @@ PostgreSQL documentation
|
|||||||
|
|
||||||
<refsynopsisdiv>
|
<refsynopsisdiv>
|
||||||
<synopsis>
|
<synopsis>
|
||||||
ANALYZE [ VERBOSE ] [ <replaceable class="PARAMETER">table_name</replaceable> [ ( <replaceable class="PARAMETER">column_name</replaceable> [, ...] ) ] ]
|
ANALYZE [ VERBOSE ] [ <replaceable class="PARAMETER">table_and_columns</replaceable> [, ...] ]
|
||||||
|
|
||||||
|
<phrase>where <replaceable class="PARAMETER">table_and_columns</replaceable> is:</phrase>
|
||||||
|
|
||||||
|
<replaceable class="PARAMETER">table_name</replaceable> [ ( <replaceable class="PARAMETER">column_name</replaceable> [, ...] ) ]
|
||||||
</synopsis>
|
</synopsis>
|
||||||
</refsynopsisdiv>
|
</refsynopsisdiv>
|
||||||
|
|
||||||
@ -38,9 +42,11 @@ ANALYZE [ VERBOSE ] [ <replaceable class="PARAMETER">table_name</replaceable> [
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
With no parameter, <command>ANALYZE</command> examines every table in the
|
Without a <replaceable class="PARAMETER">table_and_columns</replaceable>
|
||||||
current database. With a parameter, <command>ANALYZE</command> examines
|
list, <command>ANALYZE</command> processes every table and materialized view
|
||||||
only that table. It is further possible to give a list of column names,
|
in the current database that the current user has permission to analyze.
|
||||||
|
With a list, <command>ANALYZE</command> processes only those table(s).
|
||||||
|
It is further possible to give a list of column names for a table,
|
||||||
in which case only the statistics for those columns are collected.
|
in which case only the statistics for those columns are collected.
|
||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
@ -21,9 +21,20 @@ PostgreSQL documentation
|
|||||||
|
|
||||||
<refsynopsisdiv>
|
<refsynopsisdiv>
|
||||||
<synopsis>
|
<synopsis>
|
||||||
VACUUM [ ( { FULL | FREEZE | VERBOSE | ANALYZE | DISABLE_PAGE_SKIPPING } [, ...] ) ] [ <replaceable class="PARAMETER">table_name</replaceable> [ (<replaceable class="PARAMETER">column_name</replaceable> [, ...] ) ] ]
|
VACUUM [ ( <replaceable class="PARAMETER">option</replaceable> [, ...] ) ] [ <replaceable class="PARAMETER">table_and_columns</replaceable> [, ...] ]
|
||||||
VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ <replaceable class="PARAMETER">table_name</replaceable> ]
|
VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ ANALYZE ] [ <replaceable class="PARAMETER">table_and_columns</replaceable> [, ...] ]
|
||||||
VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] ANALYZE [ <replaceable class="PARAMETER">table_name</replaceable> [ (<replaceable class="PARAMETER">column_name</replaceable> [, ...] ) ] ]
|
|
||||||
|
<phrase>where <replaceable class="PARAMETER">option</replaceable> can be one of:</phrase>
|
||||||
|
|
||||||
|
FULL
|
||||||
|
FREEZE
|
||||||
|
VERBOSE
|
||||||
|
ANALYZE
|
||||||
|
DISABLE_PAGE_SKIPPING
|
||||||
|
|
||||||
|
<phrase>and <replaceable class="PARAMETER">table_and_columns</replaceable> is:</phrase>
|
||||||
|
|
||||||
|
<replaceable class="PARAMETER">table_name</replaceable> [ ( <replaceable class="PARAMETER">column_name</replaceable> [, ...] ) ]
|
||||||
</synopsis>
|
</synopsis>
|
||||||
</refsynopsisdiv>
|
</refsynopsisdiv>
|
||||||
|
|
||||||
@ -40,9 +51,10 @@ VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] ANALYZE [ <replaceable class="PARAMETER">
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
With no parameter, <command>VACUUM</command> processes every table in the
|
Without a <replaceable class="PARAMETER">table_and_columns</replaceable>
|
||||||
current database that the current user has permission to vacuum.
|
list, <command>VACUUM</command> processes every table and materialized view
|
||||||
With a parameter, <command>VACUUM</command> processes only that table.
|
in the current database that the current user has permission to vacuum.
|
||||||
|
With a list, <command>VACUUM</command> processes only those table(s).
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@ -141,8 +153,8 @@ VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] ANALYZE [ <replaceable class="PARAMETER">
|
|||||||
except when performing an aggressive vacuum, some pages may be skipped
|
except when performing an aggressive vacuum, some pages may be skipped
|
||||||
in order to avoid waiting for other sessions to finish using them.
|
in order to avoid waiting for other sessions to finish using them.
|
||||||
This option disables all page-skipping behavior, and is intended to
|
This option disables all page-skipping behavior, and is intended to
|
||||||
be used only the contents of the visibility map are thought to
|
be used only when the contents of the visibility map are
|
||||||
be suspect, which should happen only if there is a hardware or software
|
suspect, which should happen only if there is a hardware or software
|
||||||
issue causing database corruption.
|
issue causing database corruption.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
@ -152,9 +164,8 @@ VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] ANALYZE [ <replaceable class="PARAMETER">
|
|||||||
<term><replaceable class="PARAMETER">table_name</replaceable></term>
|
<term><replaceable class="PARAMETER">table_name</replaceable></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
The name (optionally schema-qualified) of a specific table to
|
The name (optionally schema-qualified) of a specific table or
|
||||||
vacuum. If omitted, all regular tables and materialized views in the
|
materialized view to vacuum. If the specified table is a partitioned
|
||||||
current database are vacuumed. If the specified table is a partitioned
|
|
||||||
table, all of its leaf partitions are vacuumed.
|
table, all of its leaf partitions are vacuumed.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
@ -165,7 +176,8 @@ VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] ANALYZE [ <replaceable class="PARAMETER">
|
|||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
The name of a specific column to analyze. Defaults to all columns.
|
The name of a specific column to analyze. Defaults to all columns.
|
||||||
If a column list is specified, <literal>ANALYZE</> is implied.
|
If a column list is specified, <literal>ANALYZE</> must also be
|
||||||
|
specified.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include "commands/cluster.h"
|
#include "commands/cluster.h"
|
||||||
#include "commands/vacuum.h"
|
#include "commands/vacuum.h"
|
||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
|
#include "nodes/makefuncs.h"
|
||||||
#include "pgstat.h"
|
#include "pgstat.h"
|
||||||
#include "postmaster/autovacuum.h"
|
#include "postmaster/autovacuum.h"
|
||||||
#include "storage/bufmgr.h"
|
#include "storage/bufmgr.h"
|
||||||
@ -67,7 +68,8 @@ static BufferAccessStrategy vac_strategy;
|
|||||||
|
|
||||||
|
|
||||||
/* non-export function prototypes */
|
/* non-export function prototypes */
|
||||||
static List *get_rel_oids(Oid relid, const RangeVar *vacrel);
|
static List *expand_vacuum_rel(VacuumRelation *vrel);
|
||||||
|
static List *get_all_vacuum_rels(void);
|
||||||
static void vac_truncate_clog(TransactionId frozenXID,
|
static void vac_truncate_clog(TransactionId frozenXID,
|
||||||
MultiXactId minMulti,
|
MultiXactId minMulti,
|
||||||
TransactionId lastSaneFrozenXid,
|
TransactionId lastSaneFrozenXid,
|
||||||
@ -90,9 +92,26 @@ ExecVacuum(VacuumStmt *vacstmt, bool isTopLevel)
|
|||||||
Assert(vacstmt->options & (VACOPT_VACUUM | VACOPT_ANALYZE));
|
Assert(vacstmt->options & (VACOPT_VACUUM | VACOPT_ANALYZE));
|
||||||
Assert((vacstmt->options & VACOPT_VACUUM) ||
|
Assert((vacstmt->options & VACOPT_VACUUM) ||
|
||||||
!(vacstmt->options & (VACOPT_FULL | VACOPT_FREEZE)));
|
!(vacstmt->options & (VACOPT_FULL | VACOPT_FREEZE)));
|
||||||
Assert((vacstmt->options & VACOPT_ANALYZE) || vacstmt->va_cols == NIL);
|
|
||||||
Assert(!(vacstmt->options & VACOPT_SKIPTOAST));
|
Assert(!(vacstmt->options & VACOPT_SKIPTOAST));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure VACOPT_ANALYZE is specified if any column lists are present.
|
||||||
|
*/
|
||||||
|
if (!(vacstmt->options & VACOPT_ANALYZE))
|
||||||
|
{
|
||||||
|
ListCell *lc;
|
||||||
|
|
||||||
|
foreach(lc, vacstmt->rels)
|
||||||
|
{
|
||||||
|
VacuumRelation *vrel = lfirst_node(VacuumRelation, lc);
|
||||||
|
|
||||||
|
if (vrel->va_cols != NIL)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
|
errmsg("ANALYZE option must be specified when a column list is provided")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* All freeze ages are zero if the FREEZE option is given; otherwise pass
|
* All freeze ages are zero if the FREEZE option is given; otherwise pass
|
||||||
* them as -1 which means to use the default values.
|
* them as -1 which means to use the default values.
|
||||||
@ -119,26 +138,22 @@ ExecVacuum(VacuumStmt *vacstmt, bool isTopLevel)
|
|||||||
params.log_min_duration = -1;
|
params.log_min_duration = -1;
|
||||||
|
|
||||||
/* Now go through the common routine */
|
/* Now go through the common routine */
|
||||||
vacuum(vacstmt->options, vacstmt->relation, InvalidOid, ¶ms,
|
vacuum(vacstmt->options, vacstmt->rels, ¶ms, NULL, isTopLevel);
|
||||||
vacstmt->va_cols, NULL, isTopLevel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Primary entry point for VACUUM and ANALYZE commands.
|
* Internal entry point for VACUUM and ANALYZE commands.
|
||||||
*
|
*
|
||||||
* options is a bitmask of VacuumOption flags, indicating what to do.
|
* options is a bitmask of VacuumOption flags, indicating what to do.
|
||||||
*
|
*
|
||||||
* relid, if not InvalidOid, indicates the relation to process; otherwise,
|
* relations, if not NIL, is a list of VacuumRelation to process; otherwise,
|
||||||
* if a RangeVar is supplied, that's what to process; otherwise, we process
|
* we process all relevant tables in the database. For each VacuumRelation,
|
||||||
* all relevant tables in the database. (If both relid and a RangeVar are
|
* if a valid OID is supplied, the table with that OID is what to process;
|
||||||
* supplied, the relid is what is processed, but we use the RangeVar's name
|
* otherwise, the VacuumRelation's RangeVar indicates what to process.
|
||||||
* to report any open/lock failure.)
|
|
||||||
*
|
*
|
||||||
* params contains a set of parameters that can be used to customize the
|
* params contains a set of parameters that can be used to customize the
|
||||||
* behavior.
|
* behavior.
|
||||||
*
|
*
|
||||||
* va_cols is a list of columns to analyze, or NIL to process them all.
|
|
||||||
*
|
|
||||||
* bstrategy is normally given as NULL, but in autovacuum it can be passed
|
* bstrategy is normally given as NULL, but in autovacuum it can be passed
|
||||||
* in to use the same buffer strategy object across multiple vacuum() calls.
|
* in to use the same buffer strategy object across multiple vacuum() calls.
|
||||||
*
|
*
|
||||||
@ -148,14 +163,14 @@ ExecVacuum(VacuumStmt *vacstmt, bool isTopLevel)
|
|||||||
* memory context that will not disappear at transaction commit.
|
* memory context that will not disappear at transaction commit.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
vacuum(int options, RangeVar *relation, Oid relid, VacuumParams *params,
|
vacuum(int options, List *relations, VacuumParams *params,
|
||||||
List *va_cols, BufferAccessStrategy bstrategy, bool isTopLevel)
|
BufferAccessStrategy bstrategy, bool isTopLevel)
|
||||||
{
|
{
|
||||||
|
static bool in_vacuum = false;
|
||||||
|
|
||||||
const char *stmttype;
|
const char *stmttype;
|
||||||
volatile bool in_outer_xact,
|
volatile bool in_outer_xact,
|
||||||
use_own_xacts;
|
use_own_xacts;
|
||||||
List *relations;
|
|
||||||
static bool in_vacuum = false;
|
|
||||||
|
|
||||||
Assert(params != NULL);
|
Assert(params != NULL);
|
||||||
|
|
||||||
@ -228,10 +243,29 @@ vacuum(int options, RangeVar *relation, Oid relid, VacuumParams *params,
|
|||||||
vac_strategy = bstrategy;
|
vac_strategy = bstrategy;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Build list of relation OID(s) to process, putting it in vac_context for
|
* Build list of relation(s) to process, putting any new data in
|
||||||
* safekeeping.
|
* vac_context for safekeeping.
|
||||||
*/
|
*/
|
||||||
relations = get_rel_oids(relid, relation);
|
if (relations != NIL)
|
||||||
|
{
|
||||||
|
List *newrels = NIL;
|
||||||
|
ListCell *lc;
|
||||||
|
|
||||||
|
foreach(lc, relations)
|
||||||
|
{
|
||||||
|
VacuumRelation *vrel = lfirst_node(VacuumRelation, lc);
|
||||||
|
List *sublist;
|
||||||
|
MemoryContext old_context;
|
||||||
|
|
||||||
|
sublist = expand_vacuum_rel(vrel);
|
||||||
|
old_context = MemoryContextSwitchTo(vac_context);
|
||||||
|
newrels = list_concat(newrels, sublist);
|
||||||
|
MemoryContextSwitchTo(old_context);
|
||||||
|
}
|
||||||
|
relations = newrels;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
relations = get_all_vacuum_rels();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Decide whether we need to start/commit our own transactions.
|
* Decide whether we need to start/commit our own transactions.
|
||||||
@ -282,7 +316,7 @@ vacuum(int options, RangeVar *relation, Oid relid, VacuumParams *params,
|
|||||||
CommitTransactionCommand();
|
CommitTransactionCommand();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Turn vacuum cost accounting on or off */
|
/* Turn vacuum cost accounting on or off, and set/clear in_vacuum */
|
||||||
PG_TRY();
|
PG_TRY();
|
||||||
{
|
{
|
||||||
ListCell *cur;
|
ListCell *cur;
|
||||||
@ -299,11 +333,11 @@ vacuum(int options, RangeVar *relation, Oid relid, VacuumParams *params,
|
|||||||
*/
|
*/
|
||||||
foreach(cur, relations)
|
foreach(cur, relations)
|
||||||
{
|
{
|
||||||
Oid relid = lfirst_oid(cur);
|
VacuumRelation *vrel = lfirst_node(VacuumRelation, cur);
|
||||||
|
|
||||||
if (options & VACOPT_VACUUM)
|
if (options & VACOPT_VACUUM)
|
||||||
{
|
{
|
||||||
if (!vacuum_rel(relid, relation, options, params))
|
if (!vacuum_rel(vrel->oid, vrel->relation, options, params))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -320,8 +354,8 @@ vacuum(int options, RangeVar *relation, Oid relid, VacuumParams *params,
|
|||||||
PushActiveSnapshot(GetTransactionSnapshot());
|
PushActiveSnapshot(GetTransactionSnapshot());
|
||||||
}
|
}
|
||||||
|
|
||||||
analyze_rel(relid, relation, options, params,
|
analyze_rel(vrel->oid, vrel->relation, options, params,
|
||||||
va_cols, in_outer_xact, vac_strategy);
|
vrel->va_cols, in_outer_xact, vac_strategy);
|
||||||
|
|
||||||
if (use_own_xacts)
|
if (use_own_xacts)
|
||||||
{
|
{
|
||||||
@ -375,25 +409,33 @@ vacuum(int options, RangeVar *relation, Oid relid, VacuumParams *params,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Build a list of Oids for each relation to be processed
|
* Given a VacuumRelation, fill in the table OID if it wasn't specified,
|
||||||
|
* and optionally add VacuumRelations for partitions of the table.
|
||||||
*
|
*
|
||||||
* The list is built in vac_context so that it will survive across our
|
* If a VacuumRelation does not have an OID supplied and is a partitioned
|
||||||
* per-relation transactions.
|
* table, an extra entry will be added to the output for each partition.
|
||||||
|
* Presently, only autovacuum supplies OIDs when calling vacuum(), and
|
||||||
|
* it does not want us to expand partitioned tables.
|
||||||
|
*
|
||||||
|
* We take care not to modify the input data structure, but instead build
|
||||||
|
* new VacuumRelation(s) to return. (But note that they will reference
|
||||||
|
* unmodified parts of the input, eg column lists.) New data structures
|
||||||
|
* are made in vac_context.
|
||||||
*/
|
*/
|
||||||
static List *
|
static List *
|
||||||
get_rel_oids(Oid relid, const RangeVar *vacrel)
|
expand_vacuum_rel(VacuumRelation *vrel)
|
||||||
{
|
{
|
||||||
List *oid_list = NIL;
|
List *vacrels = NIL;
|
||||||
MemoryContext oldcontext;
|
MemoryContext oldcontext;
|
||||||
|
|
||||||
/* OID supplied by VACUUM's caller? */
|
/* If caller supplied OID, there's nothing we need do here. */
|
||||||
if (OidIsValid(relid))
|
if (OidIsValid(vrel->oid))
|
||||||
{
|
{
|
||||||
oldcontext = MemoryContextSwitchTo(vac_context);
|
oldcontext = MemoryContextSwitchTo(vac_context);
|
||||||
oid_list = lappend_oid(oid_list, relid);
|
vacrels = lappend(vacrels, vrel);
|
||||||
MemoryContextSwitchTo(oldcontext);
|
MemoryContextSwitchTo(oldcontext);
|
||||||
}
|
}
|
||||||
else if (vacrel)
|
else
|
||||||
{
|
{
|
||||||
/* Process a specific relation, and possibly partitions thereof */
|
/* Process a specific relation, and possibly partitions thereof */
|
||||||
Oid relid;
|
Oid relid;
|
||||||
@ -406,7 +448,16 @@ get_rel_oids(Oid relid, const RangeVar *vacrel)
|
|||||||
* below, as well as find_all_inheritors's expectation that the caller
|
* below, as well as find_all_inheritors's expectation that the caller
|
||||||
* holds some lock on the starting relation.
|
* holds some lock on the starting relation.
|
||||||
*/
|
*/
|
||||||
relid = RangeVarGetRelid(vacrel, AccessShareLock, false);
|
relid = RangeVarGetRelid(vrel->relation, AccessShareLock, false);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make a returnable VacuumRelation for this rel.
|
||||||
|
*/
|
||||||
|
oldcontext = MemoryContextSwitchTo(vac_context);
|
||||||
|
vacrels = lappend(vacrels, makeVacuumRelation(vrel->relation,
|
||||||
|
relid,
|
||||||
|
vrel->va_cols));
|
||||||
|
MemoryContextSwitchTo(oldcontext);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* To check whether the relation is a partitioned table, fetch its
|
* To check whether the relation is a partitioned table, fetch its
|
||||||
@ -420,19 +471,36 @@ get_rel_oids(Oid relid, const RangeVar *vacrel)
|
|||||||
ReleaseSysCache(tuple);
|
ReleaseSysCache(tuple);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make relation list entries for this rel and its partitions, if any.
|
* If it is, make relation list entries for its partitions. Note that
|
||||||
* Note that the list returned by find_all_inheritors() includes the
|
* the list returned by find_all_inheritors() includes the passed-in
|
||||||
* passed-in OID at its head. There's no point in taking locks on the
|
* OID, so we have to skip that. There's no point in taking locks on
|
||||||
* individual partitions yet, and doing so would just add unnecessary
|
* the individual partitions yet, and doing so would just add
|
||||||
* deadlock risk.
|
* unnecessary deadlock risk.
|
||||||
|
*/
|
||||||
|
if (include_parts)
|
||||||
|
{
|
||||||
|
List *part_oids = find_all_inheritors(relid, NoLock, NULL);
|
||||||
|
ListCell *part_lc;
|
||||||
|
|
||||||
|
foreach(part_lc, part_oids)
|
||||||
|
{
|
||||||
|
Oid part_oid = lfirst_oid(part_lc);
|
||||||
|
|
||||||
|
if (part_oid == relid)
|
||||||
|
continue; /* ignore original table */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We omit a RangeVar since it wouldn't be appropriate to
|
||||||
|
* complain about failure to open one of these relations
|
||||||
|
* later.
|
||||||
*/
|
*/
|
||||||
oldcontext = MemoryContextSwitchTo(vac_context);
|
oldcontext = MemoryContextSwitchTo(vac_context);
|
||||||
if (include_parts)
|
vacrels = lappend(vacrels, makeVacuumRelation(NULL,
|
||||||
oid_list = list_concat(oid_list,
|
part_oid,
|
||||||
find_all_inheritors(relid, NoLock, NULL));
|
vrel->va_cols));
|
||||||
else
|
|
||||||
oid_list = lappend_oid(oid_list, relid);
|
|
||||||
MemoryContextSwitchTo(oldcontext);
|
MemoryContextSwitchTo(oldcontext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Release lock again. This means that by the time we actually try to
|
* Release lock again. This means that by the time we actually try to
|
||||||
@ -447,12 +515,18 @@ get_rel_oids(Oid relid, const RangeVar *vacrel)
|
|||||||
*/
|
*/
|
||||||
UnlockRelationOid(relid, AccessShareLock);
|
UnlockRelationOid(relid, AccessShareLock);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
return vacrels;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Process all plain relations and materialized views listed in
|
* Construct a list of VacuumRelations for all vacuumable rels in
|
||||||
* pg_class
|
* the current database. The list is built in vac_context.
|
||||||
*/
|
*/
|
||||||
|
static List *
|
||||||
|
get_all_vacuum_rels(void)
|
||||||
|
{
|
||||||
|
List *vacrels = NIL;
|
||||||
Relation pgclass;
|
Relation pgclass;
|
||||||
HeapScanDesc scan;
|
HeapScanDesc scan;
|
||||||
HeapTuple tuple;
|
HeapTuple tuple;
|
||||||
@ -464,28 +538,34 @@ get_rel_oids(Oid relid, const RangeVar *vacrel)
|
|||||||
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
|
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
|
||||||
{
|
{
|
||||||
Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple);
|
Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple);
|
||||||
|
MemoryContext oldcontext;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We include partitioned tables here; depending on which
|
* We include partitioned tables here; depending on which operation is
|
||||||
* operation is to be performed, caller will decide whether to
|
* to be performed, caller will decide whether to process or ignore
|
||||||
* process or ignore them.
|
* them.
|
||||||
*/
|
*/
|
||||||
if (classForm->relkind != RELKIND_RELATION &&
|
if (classForm->relkind != RELKIND_RELATION &&
|
||||||
classForm->relkind != RELKIND_MATVIEW &&
|
classForm->relkind != RELKIND_MATVIEW &&
|
||||||
classForm->relkind != RELKIND_PARTITIONED_TABLE)
|
classForm->relkind != RELKIND_PARTITIONED_TABLE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Make a relation list entry for this rel */
|
/*
|
||||||
|
* Build VacuumRelation(s) specifying the table OIDs to be processed.
|
||||||
|
* We omit a RangeVar since it wouldn't be appropriate to complain
|
||||||
|
* about failure to open one of these relations later.
|
||||||
|
*/
|
||||||
oldcontext = MemoryContextSwitchTo(vac_context);
|
oldcontext = MemoryContextSwitchTo(vac_context);
|
||||||
oid_list = lappend_oid(oid_list, HeapTupleGetOid(tuple));
|
vacrels = lappend(vacrels, makeVacuumRelation(NULL,
|
||||||
|
HeapTupleGetOid(tuple),
|
||||||
|
NIL));
|
||||||
MemoryContextSwitchTo(oldcontext);
|
MemoryContextSwitchTo(oldcontext);
|
||||||
}
|
}
|
||||||
|
|
||||||
heap_endscan(scan);
|
heap_endscan(scan);
|
||||||
heap_close(pgclass, AccessShareLock);
|
heap_close(pgclass, AccessShareLock);
|
||||||
}
|
|
||||||
|
|
||||||
return oid_list;
|
return vacrels;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -3766,7 +3766,18 @@ _copyVacuumStmt(const VacuumStmt *from)
|
|||||||
VacuumStmt *newnode = makeNode(VacuumStmt);
|
VacuumStmt *newnode = makeNode(VacuumStmt);
|
||||||
|
|
||||||
COPY_SCALAR_FIELD(options);
|
COPY_SCALAR_FIELD(options);
|
||||||
|
COPY_NODE_FIELD(rels);
|
||||||
|
|
||||||
|
return newnode;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VacuumRelation *
|
||||||
|
_copyVacuumRelation(const VacuumRelation *from)
|
||||||
|
{
|
||||||
|
VacuumRelation *newnode = makeNode(VacuumRelation);
|
||||||
|
|
||||||
COPY_NODE_FIELD(relation);
|
COPY_NODE_FIELD(relation);
|
||||||
|
COPY_SCALAR_FIELD(oid);
|
||||||
COPY_NODE_FIELD(va_cols);
|
COPY_NODE_FIELD(va_cols);
|
||||||
|
|
||||||
return newnode;
|
return newnode;
|
||||||
@ -5215,6 +5226,9 @@ copyObjectImpl(const void *from)
|
|||||||
case T_VacuumStmt:
|
case T_VacuumStmt:
|
||||||
retval = _copyVacuumStmt(from);
|
retval = _copyVacuumStmt(from);
|
||||||
break;
|
break;
|
||||||
|
case T_VacuumRelation:
|
||||||
|
retval = _copyVacuumRelation(from);
|
||||||
|
break;
|
||||||
case T_ExplainStmt:
|
case T_ExplainStmt:
|
||||||
retval = _copyExplainStmt(from);
|
retval = _copyExplainStmt(from);
|
||||||
break;
|
break;
|
||||||
|
@ -1663,7 +1663,16 @@ static bool
|
|||||||
_equalVacuumStmt(const VacuumStmt *a, const VacuumStmt *b)
|
_equalVacuumStmt(const VacuumStmt *a, const VacuumStmt *b)
|
||||||
{
|
{
|
||||||
COMPARE_SCALAR_FIELD(options);
|
COMPARE_SCALAR_FIELD(options);
|
||||||
|
COMPARE_NODE_FIELD(rels);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
_equalVacuumRelation(const VacuumRelation *a, const VacuumRelation *b)
|
||||||
|
{
|
||||||
COMPARE_NODE_FIELD(relation);
|
COMPARE_NODE_FIELD(relation);
|
||||||
|
COMPARE_SCALAR_FIELD(oid);
|
||||||
COMPARE_NODE_FIELD(va_cols);
|
COMPARE_NODE_FIELD(va_cols);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -3361,6 +3370,9 @@ equal(const void *a, const void *b)
|
|||||||
case T_VacuumStmt:
|
case T_VacuumStmt:
|
||||||
retval = _equalVacuumStmt(a, b);
|
retval = _equalVacuumStmt(a, b);
|
||||||
break;
|
break;
|
||||||
|
case T_VacuumRelation:
|
||||||
|
retval = _equalVacuumRelation(a, b);
|
||||||
|
break;
|
||||||
case T_ExplainStmt:
|
case T_ExplainStmt:
|
||||||
retval = _equalExplainStmt(a, b);
|
retval = _equalExplainStmt(a, b);
|
||||||
break;
|
break;
|
||||||
|
@ -611,3 +611,18 @@ makeGroupingSet(GroupingSetKind kind, List *content, int location)
|
|||||||
n->location = location;
|
n->location = location;
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* makeVacuumRelation -
|
||||||
|
* create a VacuumRelation node
|
||||||
|
*/
|
||||||
|
VacuumRelation *
|
||||||
|
makeVacuumRelation(RangeVar *relation, Oid oid, List *va_cols)
|
||||||
|
{
|
||||||
|
VacuumRelation *v = makeNode(VacuumRelation);
|
||||||
|
|
||||||
|
v->relation = relation;
|
||||||
|
v->oid = oid;
|
||||||
|
v->va_cols = va_cols;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
@ -365,6 +365,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
|
|||||||
%type <list> DefACLOptionList
|
%type <list> DefACLOptionList
|
||||||
%type <ival> import_qualification_type
|
%type <ival> import_qualification_type
|
||||||
%type <importqual> import_qualification
|
%type <importqual> import_qualification
|
||||||
|
%type <node> vacuum_relation
|
||||||
|
|
||||||
%type <list> stmtblock stmtmulti
|
%type <list> stmtblock stmtmulti
|
||||||
OptTableElementList TableElementList OptInherit definition
|
OptTableElementList TableElementList OptInherit definition
|
||||||
@ -396,6 +397,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
|
|||||||
transform_element_list transform_type_list
|
transform_element_list transform_type_list
|
||||||
TriggerTransitions TriggerReferencing
|
TriggerTransitions TriggerReferencing
|
||||||
publication_name_list
|
publication_name_list
|
||||||
|
vacuum_relation_list opt_vacuum_relation_list
|
||||||
|
|
||||||
%type <list> group_by_list
|
%type <list> group_by_list
|
||||||
%type <node> group_by_item empty_grouping_set rollup_clause cube_clause
|
%type <node> group_by_item empty_grouping_set rollup_clause cube_clause
|
||||||
@ -10147,7 +10149,7 @@ cluster_index_specification:
|
|||||||
*
|
*
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
|
VacuumStmt: VACUUM opt_full opt_freeze opt_verbose opt_vacuum_relation_list
|
||||||
{
|
{
|
||||||
VacuumStmt *n = makeNode(VacuumStmt);
|
VacuumStmt *n = makeNode(VacuumStmt);
|
||||||
n->options = VACOPT_VACUUM;
|
n->options = VACOPT_VACUUM;
|
||||||
@ -10157,22 +10159,7 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
|
|||||||
n->options |= VACOPT_FREEZE;
|
n->options |= VACOPT_FREEZE;
|
||||||
if ($4)
|
if ($4)
|
||||||
n->options |= VACOPT_VERBOSE;
|
n->options |= VACOPT_VERBOSE;
|
||||||
n->relation = NULL;
|
n->rels = $5;
|
||||||
n->va_cols = NIL;
|
|
||||||
$$ = (Node *)n;
|
|
||||||
}
|
|
||||||
| VACUUM opt_full opt_freeze opt_verbose qualified_name
|
|
||||||
{
|
|
||||||
VacuumStmt *n = makeNode(VacuumStmt);
|
|
||||||
n->options = VACOPT_VACUUM;
|
|
||||||
if ($2)
|
|
||||||
n->options |= VACOPT_FULL;
|
|
||||||
if ($3)
|
|
||||||
n->options |= VACOPT_FREEZE;
|
|
||||||
if ($4)
|
|
||||||
n->options |= VACOPT_VERBOSE;
|
|
||||||
n->relation = $5;
|
|
||||||
n->va_cols = NIL;
|
|
||||||
$$ = (Node *)n;
|
$$ = (Node *)n;
|
||||||
}
|
}
|
||||||
| VACUUM opt_full opt_freeze opt_verbose AnalyzeStmt
|
| VACUUM opt_full opt_freeze opt_verbose AnalyzeStmt
|
||||||
@ -10187,22 +10174,11 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
|
|||||||
n->options |= VACOPT_VERBOSE;
|
n->options |= VACOPT_VERBOSE;
|
||||||
$$ = (Node *)n;
|
$$ = (Node *)n;
|
||||||
}
|
}
|
||||||
| VACUUM '(' vacuum_option_list ')'
|
| VACUUM '(' vacuum_option_list ')' opt_vacuum_relation_list
|
||||||
{
|
{
|
||||||
VacuumStmt *n = makeNode(VacuumStmt);
|
VacuumStmt *n = makeNode(VacuumStmt);
|
||||||
n->options = VACOPT_VACUUM | $3;
|
n->options = VACOPT_VACUUM | $3;
|
||||||
n->relation = NULL;
|
n->rels = $5;
|
||||||
n->va_cols = NIL;
|
|
||||||
$$ = (Node *) n;
|
|
||||||
}
|
|
||||||
| VACUUM '(' vacuum_option_list ')' qualified_name opt_name_list
|
|
||||||
{
|
|
||||||
VacuumStmt *n = makeNode(VacuumStmt);
|
|
||||||
n->options = VACOPT_VACUUM | $3;
|
|
||||||
n->relation = $5;
|
|
||||||
n->va_cols = $6;
|
|
||||||
if (n->va_cols != NIL) /* implies analyze */
|
|
||||||
n->options |= VACOPT_ANALYZE;
|
|
||||||
$$ = (Node *) n;
|
$$ = (Node *) n;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
@ -10229,25 +10205,13 @@ vacuum_option_elem:
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
AnalyzeStmt:
|
AnalyzeStmt: analyze_keyword opt_verbose opt_vacuum_relation_list
|
||||||
analyze_keyword opt_verbose
|
|
||||||
{
|
{
|
||||||
VacuumStmt *n = makeNode(VacuumStmt);
|
VacuumStmt *n = makeNode(VacuumStmt);
|
||||||
n->options = VACOPT_ANALYZE;
|
n->options = VACOPT_ANALYZE;
|
||||||
if ($2)
|
if ($2)
|
||||||
n->options |= VACOPT_VERBOSE;
|
n->options |= VACOPT_VERBOSE;
|
||||||
n->relation = NULL;
|
n->rels = $3;
|
||||||
n->va_cols = NIL;
|
|
||||||
$$ = (Node *)n;
|
|
||||||
}
|
|
||||||
| analyze_keyword opt_verbose qualified_name opt_name_list
|
|
||||||
{
|
|
||||||
VacuumStmt *n = makeNode(VacuumStmt);
|
|
||||||
n->options = VACOPT_ANALYZE;
|
|
||||||
if ($2)
|
|
||||||
n->options |= VACOPT_VERBOSE;
|
|
||||||
n->relation = $3;
|
|
||||||
n->va_cols = $4;
|
|
||||||
$$ = (Node *)n;
|
$$ = (Node *)n;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
@ -10275,6 +10239,25 @@ opt_name_list:
|
|||||||
| /*EMPTY*/ { $$ = NIL; }
|
| /*EMPTY*/ { $$ = NIL; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
vacuum_relation:
|
||||||
|
qualified_name opt_name_list
|
||||||
|
{
|
||||||
|
$$ = (Node *) makeVacuumRelation($1, InvalidOid, $2);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
vacuum_relation_list:
|
||||||
|
vacuum_relation
|
||||||
|
{ $$ = list_make1($1); }
|
||||||
|
| vacuum_relation_list ',' vacuum_relation
|
||||||
|
{ $$ = lappend($1, $3); }
|
||||||
|
;
|
||||||
|
|
||||||
|
opt_vacuum_relation_list:
|
||||||
|
vacuum_relation_list { $$ = $1; }
|
||||||
|
| /*EMPTY*/ { $$ = NIL; }
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
*
|
*
|
||||||
|
@ -79,6 +79,7 @@
|
|||||||
#include "lib/ilist.h"
|
#include "lib/ilist.h"
|
||||||
#include "libpq/pqsignal.h"
|
#include "libpq/pqsignal.h"
|
||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
|
#include "nodes/makefuncs.h"
|
||||||
#include "pgstat.h"
|
#include "pgstat.h"
|
||||||
#include "postmaster/autovacuum.h"
|
#include "postmaster/autovacuum.h"
|
||||||
#include "postmaster/fork_process.h"
|
#include "postmaster/fork_process.h"
|
||||||
@ -3081,20 +3082,19 @@ relation_needs_vacanalyze(Oid relid,
|
|||||||
static void
|
static void
|
||||||
autovacuum_do_vac_analyze(autovac_table *tab, BufferAccessStrategy bstrategy)
|
autovacuum_do_vac_analyze(autovac_table *tab, BufferAccessStrategy bstrategy)
|
||||||
{
|
{
|
||||||
RangeVar rangevar;
|
RangeVar *rangevar;
|
||||||
|
VacuumRelation *rel;
|
||||||
/* Set up command parameters --- use local variables instead of palloc */
|
List *rel_list;
|
||||||
MemSet(&rangevar, 0, sizeof(rangevar));
|
|
||||||
|
|
||||||
rangevar.schemaname = tab->at_nspname;
|
|
||||||
rangevar.relname = tab->at_relname;
|
|
||||||
rangevar.location = -1;
|
|
||||||
|
|
||||||
/* Let pgstat know what we're doing */
|
/* Let pgstat know what we're doing */
|
||||||
autovac_report_activity(tab);
|
autovac_report_activity(tab);
|
||||||
|
|
||||||
vacuum(tab->at_vacoptions, &rangevar, tab->at_relid, &tab->at_params, NIL,
|
/* Set up one VacuumRelation target, identified by OID, for vacuum() */
|
||||||
bstrategy, true);
|
rangevar = makeRangeVar(tab->at_nspname, tab->at_relname, -1);
|
||||||
|
rel = makeVacuumRelation(rangevar, tab->at_relid, NIL);
|
||||||
|
rel_list = list_make1(rel);
|
||||||
|
|
||||||
|
vacuum(tab->at_vacoptions, rel_list, &tab->at_params, bstrategy, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -157,8 +157,7 @@ extern int vacuum_multixact_freeze_table_age;
|
|||||||
|
|
||||||
/* in commands/vacuum.c */
|
/* in commands/vacuum.c */
|
||||||
extern void ExecVacuum(VacuumStmt *vacstmt, bool isTopLevel);
|
extern void ExecVacuum(VacuumStmt *vacstmt, bool isTopLevel);
|
||||||
extern void vacuum(int options, RangeVar *relation, Oid relid,
|
extern void vacuum(int options, List *relations, VacuumParams *params,
|
||||||
VacuumParams *params, List *va_cols,
|
|
||||||
BufferAccessStrategy bstrategy, bool isTopLevel);
|
BufferAccessStrategy bstrategy, bool isTopLevel);
|
||||||
extern void vac_open_indexes(Relation relation, LOCKMODE lockmode,
|
extern void vac_open_indexes(Relation relation, LOCKMODE lockmode,
|
||||||
int *nindexes, Relation **Irel);
|
int *nindexes, Relation **Irel);
|
||||||
|
@ -86,4 +86,6 @@ extern DefElem *makeDefElemExtended(char *nameSpace, char *name, Node *arg,
|
|||||||
|
|
||||||
extern GroupingSet *makeGroupingSet(GroupingSetKind kind, List *content, int location);
|
extern GroupingSet *makeGroupingSet(GroupingSetKind kind, List *content, int location);
|
||||||
|
|
||||||
|
extern VacuumRelation *makeVacuumRelation(RangeVar *relation, Oid oid, List *va_cols);
|
||||||
|
|
||||||
#endif /* MAKEFUNC_H */
|
#endif /* MAKEFUNC_H */
|
||||||
|
@ -468,6 +468,7 @@ typedef enum NodeTag
|
|||||||
T_PartitionBoundSpec,
|
T_PartitionBoundSpec,
|
||||||
T_PartitionRangeDatum,
|
T_PartitionRangeDatum,
|
||||||
T_PartitionCmd,
|
T_PartitionCmd,
|
||||||
|
T_VacuumRelation,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TAGS FOR REPLICATION GRAMMAR PARSE NODES (replnodes.h)
|
* TAGS FOR REPLICATION GRAMMAR PARSE NODES (replnodes.h)
|
||||||
|
@ -1778,8 +1778,8 @@ typedef struct AlterTableCmd /* one subcommand of an ALTER TABLE */
|
|||||||
AlterTableType subtype; /* Type of table alteration to apply */
|
AlterTableType subtype; /* Type of table alteration to apply */
|
||||||
char *name; /* column, constraint, or trigger to act on,
|
char *name; /* column, constraint, or trigger to act on,
|
||||||
* or tablespace */
|
* or tablespace */
|
||||||
int16 num; /* attribute number for columns referenced
|
int16 num; /* attribute number for columns referenced by
|
||||||
* by number */
|
* number */
|
||||||
RoleSpec *newowner;
|
RoleSpec *newowner;
|
||||||
Node *def; /* definition of new column, index,
|
Node *def; /* definition of new column, index,
|
||||||
* constraint, or parent table */
|
* constraint, or parent table */
|
||||||
@ -3098,12 +3098,26 @@ typedef enum VacuumOption
|
|||||||
VACOPT_DISABLE_PAGE_SKIPPING = 1 << 7 /* don't skip any pages */
|
VACOPT_DISABLE_PAGE_SKIPPING = 1 << 7 /* don't skip any pages */
|
||||||
} VacuumOption;
|
} VacuumOption;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Info about a single target table of VACUUM/ANALYZE.
|
||||||
|
*
|
||||||
|
* If the OID field is set, it always identifies the table to process.
|
||||||
|
* Then the relation field can be NULL; if it isn't, it's used only to report
|
||||||
|
* failure to open/lock the relation.
|
||||||
|
*/
|
||||||
|
typedef struct VacuumRelation
|
||||||
|
{
|
||||||
|
NodeTag type;
|
||||||
|
RangeVar *relation; /* table name to process, or NULL */
|
||||||
|
Oid oid; /* table's OID; InvalidOid if not looked up */
|
||||||
|
List *va_cols; /* list of column names, or NIL for all */
|
||||||
|
} VacuumRelation;
|
||||||
|
|
||||||
typedef struct VacuumStmt
|
typedef struct VacuumStmt
|
||||||
{
|
{
|
||||||
NodeTag type;
|
NodeTag type;
|
||||||
int options; /* OR of VacuumOption flags */
|
int options; /* OR of VacuumOption flags */
|
||||||
RangeVar *relation; /* single table to process, or NULL */
|
List *rels; /* list of VacuumRelation, or NIL for all */
|
||||||
List *va_cols; /* list of column names, or NIL for all */
|
|
||||||
} VacuumStmt;
|
} VacuumStmt;
|
||||||
|
|
||||||
/* ----------------------
|
/* ----------------------
|
||||||
|
@ -80,8 +80,6 @@ CONTEXT: SQL function "do_analyze" statement 1
|
|||||||
SQL function "wrap_do_analyze" statement 1
|
SQL function "wrap_do_analyze" statement 1
|
||||||
VACUUM FULL vactst;
|
VACUUM FULL vactst;
|
||||||
VACUUM (DISABLE_PAGE_SKIPPING) vaccluster;
|
VACUUM (DISABLE_PAGE_SKIPPING) vaccluster;
|
||||||
DROP TABLE vaccluster;
|
|
||||||
DROP TABLE vactst;
|
|
||||||
-- partitioned table
|
-- partitioned table
|
||||||
CREATE TABLE vacparted (a int, b char) PARTITION BY LIST (a);
|
CREATE TABLE vacparted (a int, b char) PARTITION BY LIST (a);
|
||||||
CREATE TABLE vacparted1 PARTITION OF vacparted FOR VALUES IN (1);
|
CREATE TABLE vacparted1 PARTITION OF vacparted FOR VALUES IN (1);
|
||||||
@ -95,4 +93,25 @@ VACUUM ANALYZE vacparted(a,b,a);
|
|||||||
ERROR: column "a" of relation "vacparted" appears more than once
|
ERROR: column "a" of relation "vacparted" appears more than once
|
||||||
ANALYZE vacparted(a,b,b);
|
ANALYZE vacparted(a,b,b);
|
||||||
ERROR: column "b" of relation "vacparted" appears more than once
|
ERROR: column "b" of relation "vacparted" appears more than once
|
||||||
|
-- multiple tables specified
|
||||||
|
VACUUM vaccluster, vactst;
|
||||||
|
VACUUM vacparted, does_not_exist;
|
||||||
|
ERROR: relation "does_not_exist" does not exist
|
||||||
|
VACUUM (FREEZE) vacparted, vaccluster, vactst;
|
||||||
|
VACUUM (FREEZE) does_not_exist, vaccluster;
|
||||||
|
ERROR: relation "does_not_exist" does not exist
|
||||||
|
VACUUM ANALYZE vactst, vacparted (a);
|
||||||
|
VACUUM ANALYZE vactst (does_not_exist), vacparted (b);
|
||||||
|
ERROR: column "does_not_exist" of relation "vactst" does not exist
|
||||||
|
VACUUM FULL vacparted, vactst;
|
||||||
|
VACUUM FULL vactst, vacparted (a, b), vaccluster (i);
|
||||||
|
ERROR: ANALYZE option must be specified when a column list is provided
|
||||||
|
ANALYZE vactst, vacparted;
|
||||||
|
ANALYZE vacparted (b), vactst;
|
||||||
|
ANALYZE vactst, does_not_exist, vacparted;
|
||||||
|
ERROR: relation "does_not_exist" does not exist
|
||||||
|
ANALYZE vactst (i), vacparted (does_not_exist);
|
||||||
|
ERROR: column "does_not_exist" of relation "vacparted" does not exist
|
||||||
|
DROP TABLE vaccluster;
|
||||||
|
DROP TABLE vactst;
|
||||||
DROP TABLE vacparted;
|
DROP TABLE vacparted;
|
||||||
|
@ -62,9 +62,6 @@ VACUUM FULL vactst;
|
|||||||
|
|
||||||
VACUUM (DISABLE_PAGE_SKIPPING) vaccluster;
|
VACUUM (DISABLE_PAGE_SKIPPING) vaccluster;
|
||||||
|
|
||||||
DROP TABLE vaccluster;
|
|
||||||
DROP TABLE vactst;
|
|
||||||
|
|
||||||
-- partitioned table
|
-- partitioned table
|
||||||
CREATE TABLE vacparted (a int, b char) PARTITION BY LIST (a);
|
CREATE TABLE vacparted (a int, b char) PARTITION BY LIST (a);
|
||||||
CREATE TABLE vacparted1 PARTITION OF vacparted FOR VALUES IN (1);
|
CREATE TABLE vacparted1 PARTITION OF vacparted FOR VALUES IN (1);
|
||||||
@ -78,4 +75,20 @@ VACUUM (FREEZE) vacparted;
|
|||||||
VACUUM ANALYZE vacparted(a,b,a);
|
VACUUM ANALYZE vacparted(a,b,a);
|
||||||
ANALYZE vacparted(a,b,b);
|
ANALYZE vacparted(a,b,b);
|
||||||
|
|
||||||
|
-- multiple tables specified
|
||||||
|
VACUUM vaccluster, vactst;
|
||||||
|
VACUUM vacparted, does_not_exist;
|
||||||
|
VACUUM (FREEZE) vacparted, vaccluster, vactst;
|
||||||
|
VACUUM (FREEZE) does_not_exist, vaccluster;
|
||||||
|
VACUUM ANALYZE vactst, vacparted (a);
|
||||||
|
VACUUM ANALYZE vactst (does_not_exist), vacparted (b);
|
||||||
|
VACUUM FULL vacparted, vactst;
|
||||||
|
VACUUM FULL vactst, vacparted (a, b), vaccluster (i);
|
||||||
|
ANALYZE vactst, vacparted;
|
||||||
|
ANALYZE vacparted (b), vactst;
|
||||||
|
ANALYZE vactst, does_not_exist, vacparted;
|
||||||
|
ANALYZE vactst (i), vacparted (does_not_exist);
|
||||||
|
|
||||||
|
DROP TABLE vaccluster;
|
||||||
|
DROP TABLE vactst;
|
||||||
DROP TABLE vacparted;
|
DROP TABLE vacparted;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user