From 76ed77241453adfb10894eed6b03ea799a36923b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Villemain?= Date: Thu, 26 May 2011 00:35:13 +0200 Subject: [PATCH 3/7] Add "ANALYZE OSCACHE [VERBOSE] [relation];" it updates the oscache column in pg_class with, currently, dummy functions --- src/backend/commands/analyze.c | 124 ++++++++++++++++++++++++++++++++++- src/backend/parser/gram.y | 22 +++++-- src/backend/storage/buffer/bufmgr.c | 13 ++++ src/include/nodes/parsenodes.h | 3 +- src/include/parser/kwlist.h | 1 + src/include/storage/bufmgr.h | 2 + 6 files changed, 156 insertions(+), 9 deletions(-) diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c new file mode 100644 index 57188bc..a78f46c *** a/src/backend/commands/analyze.c --- b/src/backend/commands/analyze.c *************** static BufferAccessStrategy vac_strategy *** 85,90 **** --- 85,91 ---- static void do_analyze_rel(Relation onerel, VacuumStmt *vacstmt, bool inh); + static void do_oscache_analyze_rel(Relation onerel, bool inh); static void BlockSampler_Init(BlockSampler bs, BlockNumber nblocks, int samplesize); static bool BlockSampler_HasMore(BlockSampler bs); *************** analyze_rel(Oid relid, VacuumStmt *vacst *** 228,240 **** /* * Do the normal non-recursive ANALYZE. */ ! do_analyze_rel(onerel, vacstmt, false); /* * If there are child tables, do recursive ANALYZE. */ if (onerel->rd_rel->relhassubclass) ! do_analyze_rel(onerel, vacstmt, true); /* * Close source relation now, but keep lock so that no one deletes it --- 229,249 ---- /* * Do the normal non-recursive ANALYZE. */ ! if (vacstmt->options & (VACOPT_OSCACHE)) ! do_oscache_analyze_rel(onerel, false); ! else ! do_analyze_rel(onerel, vacstmt, false); /* * If there are child tables, do recursive ANALYZE. */ if (onerel->rd_rel->relhassubclass) ! { ! if (vacstmt->options & (VACOPT_OSCACHE)) ! do_oscache_analyze_rel(onerel, true); ! else ! do_analyze_rel(onerel, vacstmt, true); ! } /* * Close source relation now, but keep lock so that no one deletes it *************** cleanup: *** 623,628 **** --- 632,748 ---- /* Restore current context and release memory */ MemoryContextSwitchTo(caller_context); + MemoryContextDelete(anl_context); + anl_context = NULL; + } + + /* + * do_analyze_rel() -- analyze one relation, recursively or not + */ + static void + do_oscache_analyze_rel(Relation onerel, 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. + */ + oscache_update_relstats(onerel, + RelationGetRelationOSCacheInFork(onerel, MAIN_FORKNUM), + InvalidTransactionId); + + /* + * Same for indexes. + */ + for (ind = 0; ind < nindexes; ind++) + { + oscache_update_relstats(Irel[ind], + RelationGetRelationOSCacheInFork(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; } diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y new file mode 100644 index 1d39674..c312227 *** a/src/backend/parser/gram.y --- b/src/backend/parser/gram.y *************** static void SplitColQualList(List *qualL *** 342,348 **** %type opt_instead %type opt_unique opt_concurrently opt_verbose opt_full ! %type opt_freeze opt_default opt_recheck %type opt_binary opt_oids copy_delimiter %type copy_from --- 342,348 ---- %type opt_instead %type opt_unique opt_concurrently opt_verbose opt_full ! %type opt_freeze opt_oscache opt_default opt_recheck %type opt_binary opt_oids copy_delimiter %type copy_from *************** static void SplitColQualList(List *qualL *** 529,535 **** 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 PARSER PARTIAL PARTITION PASSING PASSWORD PLACING PLANS POSITION PRECEDING PRECISION PRESERVE PREPARE PREPARED PRIMARY --- 529,535 ---- NULLS_P NUMERIC OBJECT_P OF OFF OFFSET OIDS ON ONLY OPERATOR OPTION OPTIONS OR ! 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 *************** vacuum_option_elem: *** 7801,7811 **** ; AnalyzeStmt: ! analyze_keyword opt_verbose { VacuumStmt *n = makeNode(VacuumStmt); n->options = VACOPT_ANALYZE; if ($2) n->options |= VACOPT_VERBOSE; n->freeze_min_age = -1; n->freeze_table_age = -1; --- 7801,7813 ---- ; AnalyzeStmt: ! analyze_keyword opt_oscache opt_verbose { VacuumStmt *n = makeNode(VacuumStmt); n->options = VACOPT_ANALYZE; if ($2) + n->options |= VACOPT_OSCACHE; + if ($3) n->options |= VACOPT_VERBOSE; n->freeze_min_age = -1; n->freeze_table_age = -1; *************** AnalyzeStmt: *** 7813,7828 **** 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->freeze_min_age = -1; n->freeze_table_age = -1; ! n->relation = $3; ! n->va_cols = $4; $$ = (Node *)n; } ; --- 7815,7832 ---- n->va_cols = NIL; $$ = (Node *)n; } ! | analyze_keyword opt_oscache opt_verbose qualified_name opt_name_list { VacuumStmt *n = makeNode(VacuumStmt); n->options = VACOPT_ANALYZE; if ($2) + n->options |= VACOPT_OSCACHE; + if ($3) n->options |= VACOPT_VERBOSE; n->freeze_min_age = -1; n->freeze_table_age = -1; ! n->relation = $4; ! n->va_cols = $5; $$ = (Node *)n; } ; *************** opt_freeze: FREEZE { $$ = TRUE; *** 7845,7850 **** --- 7849,7859 ---- | /*EMPTY*/ { $$ = FALSE; } ; + opt_oscache: + OSCACHE { $$ = TRUE; } + | /*EMPTY*/ { $$ = FALSE; } + ; + opt_name_list: '(' name_list ')' { $$ = $2; } | /*EMPTY*/ { $$ = NIL; } *************** type_func_name_keyword: *** 12158,12163 **** --- 12167,12173 ---- | LIKE | NATURAL | NOTNULL + | OSCACHE | OUTER_P | OVER | OVERLAPS diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c new file mode 100644 index b12348b..670dbdf *** a/src/backend/storage/buffer/bufmgr.c --- b/src/backend/storage/buffer/bufmgr.c *************** RelationGetNumberOfBlocksInFork(Relation *** 1928,1933 **** --- 1928,1946 ---- 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; + } + /* --------------------------------------------------------------------- * DropRelFileNodeBuffers * diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h new file mode 100644 index 14937d4..bc191c2 *** a/src/include/nodes/parsenodes.h --- b/src/include/nodes/parsenodes.h *************** typedef enum VacuumOption *** 2417,2423 **** 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 } VacuumOption; typedef struct VacuumStmt --- 2417,2424 ---- 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_OSCACHE = 1 << 6 /* do OSCACHE stats analyze */ } VacuumOption; typedef struct VacuumStmt diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h new file mode 100644 index 12c2faf..95a7e3d *** a/src/include/parser/kwlist.h --- b/src/include/parser/kwlist.h *************** PG_KEYWORD("option", OPTION, UNRESERVED_ *** 264,269 **** --- 264,270 ---- 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 new file mode 100644 index b8fc87e..7d22b5a *** a/src/include/storage/bufmgr.h --- b/src/include/storage/bufmgr.h *************** extern void CheckPointBuffers(int flags) *** 179,184 **** --- 179,186 ---- extern BlockNumber BufferGetBlockNumber(Buffer buffer); extern BlockNumber RelationGetNumberOfBlocksInFork(Relation relation, ForkNumber forkNum); + extern float4 RelationGetRelationOSCacheInFork(Relation relation, + ForkNumber forkNum); extern void FlushRelationBuffers(Relation rel); extern void FlushDatabaseBuffers(Oid dbid); extern void DropRelFileNodeBuffers(RelFileNodeBackend rnode, -- 1.7.5.3