diff options
author | Cédric Villemain | 2011-04-28 03:16:01 +0000 |
---|---|---|
committer | Cédric Villemain | 2011-05-01 14:29:06 +0000 |
commit | e1476e4c410d22c355ef8668fd8170456d4dacea (patch) | |
tree | 4027385858a2548156ff9b1a02322427a628e1e6 | |
parent | 06a8dfda3d2c5a20ac69a1ebcb1580b56bb43700 (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.c | 128 | ||||
-rw-r--r-- | src/backend/parser/gram.y | 22 | ||||
-rw-r--r-- | src/backend/storage/buffer/bufmgr.c | 26 | ||||
-rw-r--r-- | src/include/nodes/parsenodes.h | 3 | ||||
-rw-r--r-- | src/include/parser/kwlist.h | 1 | ||||
-rw-r--r-- | src/include/storage/bufmgr.h | 4 |
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, |