X-Git-Url: http://www.sigaev.ru/git/gitweb.cgi?a=blobdiff_plain;f=online_analyze.c;h=b2f8199769e11b45a95b32476c4261fe5f043880;hb=3848a6cb4ae35252902d38ad1759696f66340968;hp=924cc7e8bfaac8231e6867587aadecd9d9e5f163;hpb=0e24386d7e6c4cec36f24420ea98d22dcaa836ae;p=online_analyze.git diff --git a/online_analyze.c b/online_analyze.c index 924cc7e..b2f8199 100644 --- a/online_analyze.c +++ b/online_analyze.c @@ -50,6 +50,10 @@ #include "utils/timestamp.h" #if PG_VERSION_NUM >= 90500 #include "nodes/makefuncs.h" +#if PG_VERSION_NUM >= 100000 +#include "utils/varlena.h" +#include "utils/regproc.h" +#endif #endif #endif @@ -70,6 +74,16 @@ static ExecutorEnd_hook_type oldExecutorEndHook = NULL; static ProcessUtility_hook_type oldProcessUtilityHook = NULL; #endif +typedef enum CmdKind +{ + CK_SELECT = CMD_SELECT, + CK_UPDATE = CMD_UPDATE, + CK_INSERT = CMD_INSERT, + CK_DELETE = CMD_DELETE, + CK_TRUNCATE, + CK_CREATE +} CmdKind; + typedef enum { OATT_ALL = 0x03, @@ -112,6 +126,7 @@ static HTAB *relstats = NULL; static void relstatsInit(void); +#if PG_VERSION_NUM < 100000 static int oid_cmp(const void *a, const void *b) { @@ -119,6 +134,7 @@ oid_cmp(const void *a, const void *b) return 0; return (*(Oid*)a > *(Oid*)b) ? 1 : -1; } +#endif static const char * tableListAssign(const char * newval, bool doit, TableList *tbl) @@ -337,7 +353,7 @@ makeRangeVarFromOid(Oid relOid) #endif static void -makeAnalyze(Oid relOid, CmdType operation, int64 naffected) +makeAnalyze(Oid relOid, CmdKind operation, int64 naffected) { TimestampTz now = GetCurrentTimestamp(); Relation rel; @@ -417,15 +433,20 @@ makeAnalyze(Oid relOid, CmdType operation, int64 naffected) else rstat = &dummyrstat; /* found == false for following if */ - if (found == false || rstat->rereadStat == true || naffected == 0) + if (!found) { + MemSet(rstat, 0, sizeof(*rstat)); + rstat->tableid = relOid; + newTable = true; + } - if (!found) - { - MemSet(rstat, 0, sizeof(*rstat)); - rstat->tableid = relOid; - } - Assert(rstat->tableid == relOid); + Assert(rstat->tableid == relOid); + + if (operation != CK_TRUNCATE && + (found == false || rstat->rereadStat == true)) + { + + rstat->rereadStat = false; tabentry = pgstat_fetch_stat_tabentry(relOid); @@ -442,16 +463,15 @@ makeAnalyze(Oid relOid, CmdType operation, int64 naffected) rstat->autovac_analyze_timestamp = tabentry->autovac_analyze_timestamp; rstat->analyze_timestamp = tabentry->analyze_timestamp; - rstat->rereadStat = false; - } - else - { - newTable = true; - rstat->rereadStat = true; } } - if (newTable || ( + if (naffected == 0) + rstat->rereadStat = true; + + if (newTable || + /* force analyze from after truncate */ + operation == CK_TRUNCATE || ( /* do not analyze too often, if both stamps are exceeded the go */ TimestampDifferenceExceeds(rstat->analyze_timestamp, now, online_analyze_min_interval) && TimestampDifferenceExceeds(rstat->autovac_analyze_timestamp, now, online_analyze_min_interval) && @@ -530,7 +550,25 @@ makeAnalyze(Oid relOid, CmdType operation, int64 naffected) rstat->autovac_analyze_timestamp = now; rstat->changes_since_analyze = 0; - rstat->rereadStat = true; + + switch(operation) + { + case CK_INSERT: + rstat->n_tuples += naffected; + break; + case CK_UPDATE: + rstat->n_tuples += naffected; + rstat->rereadStat = true; + break; + case CK_DELETE: + rstat->rereadStat = true; + break; + case CK_TRUNCATE: + rstat->n_tuples = 0; + break; + default: + break; + } /* update last analyze timestamp in local memory of backend */ if (tabentry) @@ -550,7 +588,25 @@ makeAnalyze(Oid relOid, CmdType operation, int64 naffected) if (tabentry) tabentry->changes_since_analyze += naffected; #endif - rstat->changes_since_analyze += naffected; + switch(operation) + { + case CK_INSERT: + rstat->changes_since_analyze += naffected; + rstat->n_tuples += naffected; + break; + case CK_UPDATE: + rstat->changes_since_analyze += 2 * naffected; + rstat->n_tuples += naffected; + case CK_DELETE: + rstat->changes_since_analyze += naffected; + break; + case CK_TRUNCATE: + rstat->changes_since_analyze = rstat->n_tuples; + rstat->n_tuples = 0; + break; + default: + break; + } } /* Reset local cache if we are over limit */ @@ -597,7 +653,7 @@ onlineAnalyzeHooker(QueryDesc *queryDesc) RangeTblEntry *rte = list_nth(queryDesc->plannedstmt->rtable, n-1); if (rte->rtekind == RTE_RELATION) - makeAnalyze(rte->relid, queryDesc->operation, naffected); + makeAnalyze(rte->relid, (CmdKind)queryDesc->operation, naffected); } } } @@ -610,22 +666,58 @@ onlineAnalyzeHooker(QueryDesc *queryDesc) #if PG_VERSION_NUM >= 90200 static void -onlineAnalyzeHookerUtility(Node *parsetree, const char *queryString, +onlineAnalyzeHookerUtility( +#if PG_VERSION_NUM >= 100000 + PlannedStmt *pstmt, +#else + Node *parsetree, +#endif + const char *queryString, #if PG_VERSION_NUM >= 90300 ProcessUtilityContext context, ParamListInfo params, +#if PG_VERSION_NUM >= 100000 + QueryEnvironment *queryEnv, +#endif #else ParamListInfo params, bool isTopLevel, #endif DestReceiver *dest, char *completionTag) { - RangeVar *tblname = NULL; + List *tblnames = NIL; + CmdKind op = CK_INSERT; +#if PG_VERSION_NUM >= 100000 + Node *parsetree = NULL; - if (IsA(parsetree, CreateTableAsStmt) && ((CreateTableAsStmt*)parsetree)->into) - tblname = (RangeVar*)copyObject(((CreateTableAsStmt*)parsetree)->into->rel); + if (pstmt->commandType == CMD_UTILITY) + parsetree = pstmt->utilityStmt; +#endif + + if (parsetree && online_analyze_enable) + { + if (IsA(parsetree, CreateTableAsStmt) && + ((CreateTableAsStmt*)parsetree)->into) + { + tblnames = + list_make1((RangeVar*)copyObject(((CreateTableAsStmt*)parsetree)->into->rel)); + op = CK_CREATE; + } + else if (IsA(parsetree, TruncateStmt)) + { + tblnames = list_copy(((TruncateStmt*)parsetree)->relations); + op = CK_TRUNCATE; + } + } + +#if PG_VERSION_NUM >= 100000 +#define parsetree pstmt +#endif if (oldProcessUtilityHook) oldProcessUtilityHook(parsetree, queryString, #if PG_VERSION_NUM >= 90300 context, params, +#if PG_VERSION_NUM >= 100000 + queryEnv, +#endif #else params, isTopLevel, #endif @@ -634,15 +726,28 @@ onlineAnalyzeHookerUtility(Node *parsetree, const char *queryString, standard_ProcessUtility(parsetree, queryString, #if PG_VERSION_NUM >= 90300 context, params, +#if PG_VERSION_NUM >= 100000 + queryEnv, +#endif #else params, isTopLevel, #endif dest, completionTag); - if (tblname) { - Oid tblOid = RangeVarGetRelid(tblname, NoLock, true); +#if PG_VERSION_NUM >= 100000 +#undef parsetree +#endif + + if (tblnames) { + ListCell *l; - makeAnalyze(tblOid, CMD_INSERT, -1); + foreach(l, tblnames) + { + RangeVar *tblname = (RangeVar*)lfirst(l); + Oid tblOid = RangeVarGetRelid(tblname, NoLock, true); + + makeAnalyze(tblOid, op, -1); + } } } #endif