summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCédric Villemain2011-04-28 03:16:01 +0000
committerCédric Villemain2011-05-01 14:29:06 +0000
commite1476e4c410d22c355ef8668fd8170456d4dacea (patch)
tree4027385858a2548156ff9b1a02322427a628e1e6
parent06a8dfda3d2c5a20ac69a1ebcb1580b56bb43700 (diff)
Add "ANALYZE OSCACHE [VERBOSE] [relation];"
it updates the relative columns in pg_class with currently dummy functions
-rw-r--r--src/backend/commands/analyze.c128
-rw-r--r--src/backend/parser/gram.y22
-rw-r--r--src/backend/storage/buffer/bufmgr.c26
-rw-r--r--src/include/nodes/parsenodes.h3
-rw-r--r--src/include/parser/kwlist.h1
-rw-r--r--src/include/storage/bufmgr.h4
6 files changed, 175 insertions, 9 deletions
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index 0568a1bcf8..284ab5db06 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -86,6 +86,8 @@ static BufferAccessStrategy vac_strategy;
static void do_analyze_rel(Relation onerel, VacuumStmt *vacstmt,
bool update_reltuples, bool inh);
+static void do_cache_analyze_rel(Relation onerel, VacuumStmt *vacstmt,
+ bool update_reltuples, bool inh);
static void BlockSampler_Init(BlockSampler bs, BlockNumber nblocks,
int samplesize);
static bool BlockSampler_HasMore(BlockSampler bs);
@@ -238,13 +240,21 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt,
/*
* Do the normal non-recursive ANALYZE.
*/
- do_analyze_rel(onerel, vacstmt, update_reltuples, false);
+ if (vacstmt->options & (VACOPT_CACHE))
+ do_cache_analyze_rel(onerel, vacstmt, update_reltuples, false);
+ else
+ do_analyze_rel(onerel, vacstmt, update_reltuples, false);
/*
* If there are child tables, do recursive ANALYZE.
*/
if (onerel->rd_rel->relhassubclass)
- do_analyze_rel(onerel, vacstmt, false, true);
+ {
+ if (vacstmt->options & (VACOPT_CACHE))
+ do_cache_analyze_rel(onerel, vacstmt, false, true);
+ else
+ do_analyze_rel(onerel, vacstmt, false, true);
+ }
/*
* Close source relation now, but keep lock so that no one deletes it
@@ -640,6 +650,120 @@ cleanup:
}
/*
+ * do_analyze_rel() -- analyze one relation, recursively or not
+ */
+static void
+do_cache_analyze_rel(Relation onerel, VacuumStmt *vacstmt,
+ bool update_relcache, bool inh)
+{
+ int ind;
+ Relation *Irel;
+ int nindexes;
+ bool hasindex;
+ AnlIndexData *indexdata;
+ PGRUsage ru0;
+ TimestampTz starttime = 0;
+ MemoryContext caller_context;
+ int save_nestlevel;
+
+ if (inh)
+ ereport(elevel,
+ (errmsg("cache analyzing \"%s.%s\" inheritance tree",
+ get_namespace_name(RelationGetNamespace(onerel)),
+ RelationGetRelationName(onerel))));
+ else
+ ereport(elevel,
+ (errmsg("cache analyzing \"%s.%s\"",
+ get_namespace_name(RelationGetNamespace(onerel)),
+ RelationGetRelationName(onerel))));
+
+ /*
+ * Set up a working context so that we can easily free whatever junk gets
+ * created.
+ */
+ anl_context = AllocSetContextCreate(CurrentMemoryContext,
+ "Analyze",
+ ALLOCSET_DEFAULT_MINSIZE,
+ ALLOCSET_DEFAULT_INITSIZE,
+ ALLOCSET_DEFAULT_MAXSIZE);
+ caller_context = MemoryContextSwitchTo(anl_context);
+
+ /*
+ * Arrange to make GUC variable changes local to this command.
+ */
+ save_nestlevel = NewGUCNestLevel();
+
+ /* measure elapsed time iff autovacuum logging requires it */
+ if (IsAutoVacuumWorkerProcess() && Log_autovacuum_min_duration >= 0)
+ {
+ pg_rusage_init(&ru0);
+ if (Log_autovacuum_min_duration > 0)
+ starttime = GetCurrentTimestamp();
+ }
+
+ /*
+ * Open all indexes of the relation, and see if there are any analyzable
+ * columns in the indexes. We do not analyze index columns if there was
+ * an explicit column list in the ANALYZE command, however. If we are
+ * doing a recursive scan, we don't want to touch the parent's indexes at
+ * all.
+ */
+ if (!inh)
+ vac_open_indexes(onerel, AccessShareLock, &nindexes, &Irel);
+ else
+ {
+ Irel = NULL;
+ nindexes = 0;
+ }
+ hasindex = (nindexes > 0);
+ indexdata = NULL;
+
+ /*
+ * Update cache stats in pg_class.
+ */
+ cache_update_relstats(onerel,
+ RelationGetRelationOSCacheInFork(onerel, MAIN_FORKNUM),
+ RelationGetRelationPGCacheInFork(onerel, MAIN_FORKNUM),
+ InvalidTransactionId);
+
+ /*
+ * Same for indexes.
+ */
+ for (ind = 0; ind < nindexes; ind++)
+ {
+ cache_update_relstats(Irel[ind],
+ RelationGetRelationOSCacheInFork(Irel[ind], MAIN_FORKNUM),
+ RelationGetRelationPGCacheInFork(Irel[ind], MAIN_FORKNUM),
+ InvalidTransactionId);
+ }
+
+ /* Done with indexes */
+ vac_close_indexes(nindexes, Irel, NoLock);
+
+ /* Log the action if appropriate */
+ if (IsAutoVacuumWorkerProcess() && Log_autovacuum_min_duration >= 0)
+ {
+ if (Log_autovacuum_min_duration == 0 ||
+ TimestampDifferenceExceeds(starttime, GetCurrentTimestamp(),
+ Log_autovacuum_min_duration))
+ ereport(LOG,
+ (errmsg("automatic cache analyze of table \"%s.%s.%s\" system usage: %s",
+ get_database_name(MyDatabaseId),
+ get_namespace_name(RelationGetNamespace(onerel)),
+ RelationGetRelationName(onerel),
+ pg_rusage_show(&ru0))));
+ }
+
+ /* Roll back any GUC changes executed by index functions */
+ AtEOXact_GUC(false, save_nestlevel);
+
+ /* Restore current context and release memory */
+ MemoryContextSwitchTo(caller_context);
+ MemoryContextDelete(anl_context);
+ anl_context = NULL;
+}
+
+/*
* Compute statistics about indexes of a relation
*/
static void
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 933a1a2ff9..34ecd292cb 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -342,7 +342,7 @@ static void SplitColQualList(List *qualList,
%type <boolean> opt_instead
%type <boolean> opt_unique opt_concurrently opt_verbose opt_full
-%type <boolean> opt_freeze opt_default opt_recheck
+%type <boolean> opt_freeze opt_oscache opt_default opt_recheck
%type <defelt> opt_binary opt_oids copy_delimiter
%type <boolean> copy_from
@@ -529,7 +529,7 @@ static void SplitColQualList(List *qualList,
NULLS_P NUMERIC
OBJECT_P OF OFF OFFSET OIDS ON ONLY OPERATOR OPTION OPTIONS OR
- ORDER OUT_P OUTER_P OVER OVERLAPS OVERLAY OWNED OWNER
+ ORDER OSCACHE OUT_P OUTER_P OVER OVERLAPS OVERLAY OWNED OWNER
PARSER PARTIAL PARTITION PASSING PASSWORD PLACING PLANS POSITION
PRECEDING PRECISION PRESERVE PREPARE PREPARED PRIMARY
@@ -7802,11 +7802,13 @@ vacuum_option_elem:
;
AnalyzeStmt:
- analyze_keyword opt_verbose
+ analyze_keyword opt_oscache opt_verbose
{
VacuumStmt *n = makeNode(VacuumStmt);
n->options = VACOPT_ANALYZE;
if ($2)
+ n->options |= VACOPT_CACHE;
+ if ($3)
n->options |= VACOPT_VERBOSE;
n->freeze_min_age = -1;
n->freeze_table_age = -1;
@@ -7814,16 +7816,18 @@ AnalyzeStmt:
n->va_cols = NIL;
$$ = (Node *)n;
}
- | analyze_keyword opt_verbose qualified_name opt_name_list
+ | analyze_keyword opt_oscache opt_verbose qualified_name opt_name_list
{
VacuumStmt *n = makeNode(VacuumStmt);
n->options = VACOPT_ANALYZE;
if ($2)
+ n->options |= VACOPT_CACHE;
+ if ($3)
n->options |= VACOPT_VERBOSE;
n->freeze_min_age = -1;
n->freeze_table_age = -1;
- n->relation = $3;
- n->va_cols = $4;
+ n->relation = $4;
+ n->va_cols = $5;
$$ = (Node *)n;
}
;
@@ -7846,6 +7850,11 @@ opt_freeze: FREEZE { $$ = TRUE; }
| /*EMPTY*/ { $$ = FALSE; }
;
+opt_oscache:
+ OSCACHE { $$ = TRUE; }
+ | /*EMPTY*/ { $$ = FALSE; }
+ ;
+
opt_name_list:
'(' name_list ')' { $$ = $2; }
| /*EMPTY*/ { $$ = NIL; }
@@ -12159,6 +12168,7 @@ type_func_name_keyword:
| LIKE
| NATURAL
| NOTNULL
+ | OSCACHE
| OUTER_P
| OVER
| OVERLAPS
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index f96685db50..301b368d37 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -1922,6 +1922,32 @@ RelationGetNumberOfBlocksInFork(Relation relation, ForkNumber forkNum)
return smgrnblocks(relation->rd_smgr, forkNum);
}
+/*
+ * RelationGetRelationOSCacheInFork
+ * Determines the current percentage of pages in OS cache for the
+ * relation.
+ */
+float4
+RelationGetRelationOSCacheInFork(Relation relation, ForkNumber forkNum)
+{
+ float4 percent = 0;
+
+ return percent;
+}
+
+/*
+ * RelationGetRelationPGCacheInFork
+ * Determines the current percentage of pages in PostgreSQL cache
+ * for the relation.
+ */
+float4
+RelationGetRelationPGCacheInFork(Relation relation, ForkNumber forkNum)
+{
+ float4 percent = 0;
+
+ return percent;
+}
+
/* ---------------------------------------------------------------------
* DropRelFileNodeBuffers
*
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index ee1881b630..bc7a3010da 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2417,7 +2417,8 @@ typedef enum VacuumOption
VACOPT_VERBOSE = 1 << 2, /* print progress info */
VACOPT_FREEZE = 1 << 3, /* FREEZE option */
VACOPT_FULL = 1 << 4, /* FULL (non-concurrent) vacuum */
- VACOPT_NOWAIT = 1 << 5
+ VACOPT_NOWAIT = 1 << 5,
+ VACOPT_CACHE = 1 << 6 /* do CACHE stats analyze */
} VacuumOption;
typedef struct VacuumStmt
diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h
index 12c2faf3de..95a7e3d320 100644
--- a/src/include/parser/kwlist.h
+++ b/src/include/parser/kwlist.h
@@ -264,6 +264,7 @@ PG_KEYWORD("option", OPTION, UNRESERVED_KEYWORD)
PG_KEYWORD("options", OPTIONS, UNRESERVED_KEYWORD)
PG_KEYWORD("or", OR, RESERVED_KEYWORD)
PG_KEYWORD("order", ORDER, RESERVED_KEYWORD)
+PG_KEYWORD("oscache", OSCACHE, TYPE_FUNC_NAME_KEYWORD)
PG_KEYWORD("out", OUT_P, COL_NAME_KEYWORD)
PG_KEYWORD("outer", OUTER_P, TYPE_FUNC_NAME_KEYWORD)
PG_KEYWORD("over", OVER, TYPE_FUNC_NAME_KEYWORD)
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index b8fc87ec57..5bcc911b22 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -179,6 +179,10 @@ extern void CheckPointBuffers(int flags);
extern BlockNumber BufferGetBlockNumber(Buffer buffer);
extern BlockNumber RelationGetNumberOfBlocksInFork(Relation relation,
ForkNumber forkNum);
+extern float4 RelationGetRelationOSCacheInFork(Relation relation,
+ ForkNumber forkNum);
+extern float4 RelationGetRelationPGCacheInFork(Relation relation,
+ ForkNumber forkNum);
extern void FlushRelationBuffers(Relation rel);
extern void FlushDatabaseBuffers(Oid dbid);
extern void DropRelFileNodeBuffers(RelFileNodeBackend rnode,