X-Git-Url: http://sigaev.ru/git/gitweb.cgi?a=blobdiff_plain;f=online_analyze.c;h=0d85df6583a8c70fb35547fbb026b28b26a401db;hb=f0071352047aa4cc7e3822101f9d30a67e12c8e3;hp=82736730167ee7e9a991cb269d3396fa28735e43;hpb=837e66bd8a47b18ef7c38210598357de001e40fe;p=online_analyze.git diff --git a/online_analyze.c b/online_analyze.c index 8273673..0d85df6 100644 --- a/online_analyze.c +++ b/online_analyze.c @@ -6,13 +6,13 @@ * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. + * may be used to endorse or promote products derived from this software + * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY CONTRIBUTORS ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -46,6 +46,9 @@ #include "utils/rel.h" #include "utils/relcache.h" #include "utils/timestamp.h" +#if PG_VERSION_NUM >= 90500 +#include "nodes/makefuncs.h" +#endif #endif #ifdef PG_MODULE_MAGIC @@ -63,7 +66,7 @@ static ExecutorEnd_hook_type oldExecutorEndHook = NULL; static ProcessUtility_hook_type oldProcessUtilityHook = NULL; #endif -typedef enum +typedef enum { OATT_ALL = 0x03, OATT_PERSISTENT = 0x01, @@ -71,7 +74,7 @@ typedef enum OATT_NONE = 0x00 } OnlineAnalyzeTableType; -static const struct config_enum_entry online_analyze_table_type_options[] = +static const struct config_enum_entry online_analyze_table_type_options[] = { {"all", OATT_ALL, false}, {"persistent", OATT_PERSISTENT, false}, @@ -102,11 +105,11 @@ oid_cmp(const void *a, const void *b) static const char * tableListAssign(const char * newval, bool doit, TableList *tbl) { - char *rawname; - List *namelist; - ListCell *l; - Oid *newOids = NULL; - int nOids = 0, + char *rawname; + List *namelist; + ListCell *l; + Oid *newOids = NULL; + int nOids = 0, i = 0; rawname = pstrdup(newval); @@ -119,18 +122,19 @@ tableListAssign(const char * newval, bool doit, TableList *tbl) nOids = list_length(namelist); newOids = malloc(sizeof(Oid) * (nOids+1)); if (!newOids) - elog(ERROR,"could not allocate %d bytes", (int)(sizeof(Oid) * (nOids+1))); + elog(ERROR,"could not allocate %d bytes", + (int)(sizeof(Oid) * (nOids+1))); } foreach(l, namelist) { - char *curname = (char *) lfirst(l); + char *curname = (char *) lfirst(l); #if PG_VERSION_NUM >= 90200 - Oid relOid = RangeVarGetRelid(makeRangeVarFromNameList(stringToQualifiedNameList(curname)), - NoLock, true); + Oid relOid = RangeVarGetRelid(makeRangeVarFromNameList( + stringToQualifiedNameList(curname)), NoLock, true); #else - Oid relOid = RangeVarGetRelid(makeRangeVarFromNameList(stringToQualifiedNameList(curname)), - true); + Oid relOid = RangeVarGetRelid(makeRangeVarFromNameList( + stringToQualifiedNameList(curname)), true); #endif if (relOid == InvalidOid) @@ -223,7 +227,7 @@ includeTablesAssign(const char *newval, void *extra) tableListAssign(newval, true, &excludeTables); } -#else /* PG_VERSION_NUM < 90100 */ +#else /* PG_VERSION_NUM < 90100 */ static const char * excludeTablesAssign(const char * newval, bool doit, GucSource source) @@ -242,8 +246,8 @@ includeTablesAssign(const char * newval, bool doit, GucSource source) static const char* tableListShow(TableList *tbl) { - char *val, *ptr; - int i, + char *val, *ptr; + int i, len; len = 1 /* \0 */ + tbl->nTables * (2 * NAMEDATALEN + 2 /* ', ' */ + 1 /* . */); @@ -251,9 +255,9 @@ tableListShow(TableList *tbl) *ptr ='\0'; for(i=0; inTables; i++) { - char *relname = get_rel_name(tbl->tables[i]); - Oid nspOid = get_rel_namespace(tbl->tables[i]); - char *nspname = get_namespace_name(nspOid); + char *relname = get_rel_name(tbl->tables[i]); + Oid nspOid = get_rel_namespace(tbl->tables[i]); + char *nspname = get_namespace_name(nspOid); if ( relname == NULL || nspOid == InvalidOid || nspname == NULL ) continue; @@ -301,17 +305,88 @@ matchOid(TableList *tbl, Oid oid) return false; } +#if PG_VERSION_NUM >= 90500 +static RangeVar* +makeRangeVarFromOid(Oid relOid) +{ + return makeRangeVar( + get_namespace_name(get_rel_namespace(relOid)), + get_rel_name(relOid), + -1 + ); + +} +#endif + static void -makeAnalyze(Oid relOid, CmdType operation, uint32 naffected) +makeAnalyze(Oid relOid, CmdType operation, int32 naffected) { PgStat_StatTabEntry *tabentry; - TimestampTz now = GetCurrentTimestamp(); + TimestampTz now = GetCurrentTimestamp(); if (relOid == InvalidOid) return; - if (get_rel_relkind(relOid) != RELKIND_RELATION) + if (naffected == 0) + /* return if there is not changes */ return; + else if (naffected < 0) + /* number if affected rows is unknown */ + naffected = 0; + + /* + * includeTables overwrites excludeTables + */ + switch(online_analyze_table_type) + { + case OATT_ALL: + if (get_rel_relkind(relOid) != RELKIND_RELATION || + (matchOid(&excludeTables, relOid) == true && + matchOid(&includeTables, relOid) == false)) + return; + break; + case OATT_NONE: + if (get_rel_relkind(relOid) != RELKIND_RELATION || + matchOid(&includeTables, relOid) == false) + return; + break; + case OATT_TEMPORARY: + case OATT_PERSISTENT: + default: + { + Relation rel; + OnlineAnalyzeTableType reltype; + + rel = RelationIdGetRelation(relOid); + + if (rel->rd_rel->relkind != RELKIND_RELATION) + { + RelationClose(rel); + return; + } + + reltype = +#if PG_VERSION_NUM >= 90100 + (rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP) +#else + (rel->rd_istemp || rel->rd_islocaltemp) +#endif + ? OATT_TEMPORARY : OATT_PERSISTENT; + RelationClose(rel); + + /* + * skip analyze if relation's type doesn't not match + * online_analyze_table_type + */ + if ((online_analyze_table_type & reltype) == 0 || + matchOid(&excludeTables, relOid) == true) + { + if (matchOid(&includeTables, relOid) == false) + return; + } + break; + } + } tabentry = pgstat_fetch_stat_tabentry(relOid); @@ -321,70 +396,37 @@ makeAnalyze(Oid relOid, CmdType operation, uint32 naffected) #define changes_since_analyze(t) ((t)->n_live_tuples + (t)->n_dead_tuples - (t)->last_anl_tuples) #endif - if ( + if ( tabentry == NULL /* a new table */ || ( /* do not analyze too often, if both stamps are exceeded the go */ - TimestampDifferenceExceeds(tabentry->analyze_timestamp, now, online_analyze_min_interval) && + TimestampDifferenceExceeds(tabentry->analyze_timestamp, now, online_analyze_min_interval) && TimestampDifferenceExceeds(tabentry->autovac_analyze_timestamp, now, online_analyze_min_interval) && /* be in sync with relation_needs_vacanalyze */ ((double)(changes_since_analyze(tabentry) + naffected)) >= - online_analyze_scale_factor * ((double)(tabentry->n_dead_tuples + tabentry->n_live_tuples)) + + online_analyze_scale_factor * ((double)(tabentry->n_dead_tuples + tabentry->n_live_tuples)) + (double)online_analyze_threshold ) ) { +#if PG_VERSION_NUM < 90500 VacuumStmt vacstmt; - TimestampTz startStamp, endStamp; - - /* - * includeTables overwrites excludeTables - */ - switch(online_analyze_table_type) - { - case OATT_ALL: - if (matchOid(&excludeTables, relOid) == true && matchOid(&includeTables, relOid) == false) - return; - break; - case OATT_NONE: - if (matchOid(&includeTables, relOid) == false) - return; - break; - case OATT_TEMPORARY: - case OATT_PERSISTENT: - default: - { - Relation rel; - OnlineAnalyzeTableType reltype; - - rel = RelationIdGetRelation(relOid); - reltype = -#if PG_VERSION_NUM >= 90100 - (rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP) #else - (rel->rd_istemp || rel->rd_islocaltemp) + VacuumParams vacstmt; #endif - ? OATT_TEMPORARY : OATT_PERSISTENT; - RelationClose(rel); + TimestampTz startStamp, endStamp; - /* - * skip analyze if relation's type doesn't not match online_analyze_table_type - */ - if ((online_analyze_table_type & reltype) == 0 || matchOid(&excludeTables, relOid) == true) - { - if (matchOid(&includeTables, relOid) == false) - return; - } - } - break; - } + memset(&startStamp, 0, sizeof(startStamp)); /* keep compiler quiet */ + + memset(&vacstmt, 0, sizeof(vacstmt)); - vacstmt.type = T_VacuumStmt; vacstmt.freeze_min_age = -1; vacstmt.freeze_table_age = -1; /* ??? */ + +#if PG_VERSION_NUM < 90500 + vacstmt.type = T_VacuumStmt; vacstmt.relation = NULL; vacstmt.va_cols = NIL; - #if PG_VERSION_NUM >= 90000 vacstmt.options = VACOPT_ANALYZE; if (online_analyze_verbose) @@ -394,13 +436,29 @@ makeAnalyze(Oid relOid, CmdType operation, uint32 naffected) vacstmt.analyze = true; vacstmt.verbose = online_analyze_verbose; #endif +#else + vacstmt.multixact_freeze_min_age = -1; + vacstmt.multixact_freeze_table_age = -1; + vacstmt.log_min_duration = -1; +#endif if (online_analyze_verbose) startStamp = GetCurrentTimestamp(); - analyze_rel(relOid, &vacstmt, GetAccessStrategy(BAS_VACUUM) -#if (PG_VERSION_NUM < 90004) && (PG_VERSION_NUM >= 90000) + analyze_rel(relOid, +#if PG_VERSION_NUM < 90500 + &vacstmt +#if PG_VERSION_NUM >= 90018 , true +#endif + , GetAccessStrategy(BAS_VACUUM) +#if (PG_VERSION_NUM >= 90000) && (PG_VERSION_NUM < 90004) + , true +#endif +#else + makeRangeVarFromOid(relOid), + VACOPT_ANALYZE | ((online_analyze_verbose) ? VACOPT_VERBOSE : 0), + &vacstmt, NULL, true, GetAccessStrategy(BAS_VACUUM) #endif ); @@ -411,11 +469,11 @@ makeAnalyze(Oid relOid, CmdType operation, uint32 naffected) endStamp = GetCurrentTimestamp(); TimestampDifference(startStamp, endStamp, &secs, µsecs); - elog(INFO, "analyze \"%s\" took %.02f seconds", - get_rel_name(relOid), ((double)secs) + ((double)microsecs)/1.0e6); + elog(INFO, "analyze \"%s\" took %.02f seconds", + get_rel_name(relOid), + ((double)secs) + ((double)microsecs)/1.0e6); } - if (tabentry == NULL) { /* new table */ @@ -437,19 +495,20 @@ makeAnalyze(Oid relOid, CmdType operation, uint32 naffected) extern PGDLLIMPORT void onlineAnalyzeHooker(QueryDesc *queryDesc); void -onlineAnalyzeHooker(QueryDesc *queryDesc) +onlineAnalyzeHooker(QueryDesc *queryDesc) { - uint32 naffected = 0; + uint32 naffected = -1; if (queryDesc->estate) - naffected = queryDesc->estate->es_processed; + naffected = queryDesc->estate->es_processed; if (online_analyze_enable && queryDesc->plannedstmt && - (queryDesc->operation == CMD_INSERT || + (queryDesc->operation == CMD_INSERT || queryDesc->operation == CMD_UPDATE || queryDesc->operation == CMD_DELETE #if PG_VERSION_NUM < 90200 - || (queryDesc->operation == CMD_SELECT && queryDesc->plannedstmt->intoClause) + || (queryDesc->operation == CMD_SELECT && + queryDesc->plannedstmt->intoClause) #endif )) { @@ -460,7 +519,7 @@ onlineAnalyzeHooker(QueryDesc *queryDesc) makeAnalyze(relOid, queryDesc->operation, naffected); } - else + else #endif if (queryDesc->plannedstmt->resultRelations && queryDesc->plannedstmt->rtable) @@ -469,9 +528,9 @@ onlineAnalyzeHooker(QueryDesc *queryDesc) foreach(l, queryDesc->plannedstmt->resultRelations) { - int n = lfirst_int(l); + int n = lfirst_int(l); RangeTblEntry *rte = list_nth(queryDesc->plannedstmt->rtable, n-1); - + if (rte->rtekind == RTE_RELATION) makeAnalyze(rte->relid, queryDesc->operation, naffected); } @@ -486,8 +545,12 @@ onlineAnalyzeHooker(QueryDesc *queryDesc) #if PG_VERSION_NUM >= 90200 static void -onlineAnalyzeHookerUtility(Node *parsetree, const char *queryString, +onlineAnalyzeHookerUtility(Node *parsetree, const char *queryString, +#if PG_VERSION_NUM >= 90300 + ProcessUtilityContext context, ParamListInfo params, +#else ParamListInfo params, bool isTopLevel, +#endif DestReceiver *dest, char *completionTag) { RangeVar *tblname = NULL; @@ -495,14 +558,26 @@ onlineAnalyzeHookerUtility(Node *parsetree, const char *queryString, tblname = (RangeVar*)copyObject(((CreateTableAsStmt*)parsetree)->into->rel); if (oldProcessUtilityHook) - oldProcessUtilityHook(parsetree, queryString, params, isTopLevel, dest, completionTag); + oldProcessUtilityHook(parsetree, queryString, +#if PG_VERSION_NUM >= 90300 + context, params, +#else + params, isTopLevel, +#endif + dest, completionTag); else - standard_ProcessUtility(parsetree, queryString, params, isTopLevel, dest, completionTag); + standard_ProcessUtility(parsetree, queryString, +#if PG_VERSION_NUM >= 90300 + context, params, +#else + params, isTopLevel, +#endif + dest, completionTag); if (tblname) { Oid tblOid = RangeVarGetRelid(tblname, NoLock, true); - makeAnalyze(tblOid, CMD_INSERT, 0); + makeAnalyze(tblOid, CMD_INSERT, -1); } } #endif @@ -560,7 +635,7 @@ _PG_init(void) NULL ); - DefineCustomRealVariable( + DefineCustomRealVariable( "online_analyze.scale_factor", "fraction of table size to start on-line analyze", "fraction of table size to start on-line analyze", @@ -581,7 +656,7 @@ _PG_init(void) NULL ); - DefineCustomIntVariable( + DefineCustomIntVariable( "online_analyze.threshold", "min number of row updates before on-line analyze", "min number of row updates before on-line analyze", @@ -602,11 +677,11 @@ _PG_init(void) NULL ); - DefineCustomRealVariable( + DefineCustomRealVariable( "online_analyze.min_interval", "minimum time interval between analyze call (in milliseconds)", "minimum time interval between analyze call (in milliseconds)", - &online_analyze_scale_factor, + &online_analyze_min_interval, #if PG_VERSION_NUM >= 80400 online_analyze_min_interval, #endif @@ -634,7 +709,7 @@ _PG_init(void) online_analyze_table_type_options, PGC_USERSET, #if PG_VERSION_NUM >= 80400 - GUC_NOT_IN_SAMPLE, + GUC_NOT_IN_SAMPLE, #if PG_VERSION_NUM >= 90100 NULL, #endif @@ -643,7 +718,7 @@ _PG_init(void) NULL ); - DefineCustomStringVariable( + DefineCustomStringVariable( "online_analyze.exclude_tables", "List of tables which will not online analyze", NULL, @@ -662,7 +737,7 @@ _PG_init(void) excludeTablesShow ); - DefineCustomStringVariable( + DefineCustomStringVariable( "online_analyze.include_tables", "List of tables which will online analyze", NULL,