Merge branch 'local_hash' into n_tuples_limit
authorTeodor Sigaev <teodor@sigaev.ru>
Fri, 7 Apr 2017 14:13:37 +0000 (17:13 +0300)
committerTeodor Sigaev <teodor@sigaev.ru>
Fri, 7 Apr 2017 14:13:37 +0000 (17:13 +0300)
1  2 
online_analyze.c

diff --combined online_analyze.c
  #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
  
@@@ -63,13 -67,22 +67,23 @@@ static double online_analyze_scale_fact
  static int online_analyze_threshold = 50;
  static int online_analyze_capacity_threshold = 100000;
  static double online_analyze_min_interval = 10000;
 +static int online_analyze_lower_limit = 0;
  
  static ExecutorEnd_hook_type oldExecutorEndHook = NULL;
  #if PG_VERSION_NUM >= 90200
  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 -125,7 +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)
  {
                return 0;
        return (*(Oid*)a > *(Oid*)b) ? 1 : -1;
  }
+ #endif
  
  static const char *
  tableListAssign(const char * newval, bool doit, TableList *tbl)
@@@ -337,7 -352,7 +353,7 @@@ makeRangeVarFromOid(Oid relOid
  #endif
  
  static void
- makeAnalyze(Oid relOid, CmdType operation, int64 naffected)
 -makeAnalyze(Oid relOid, CmdKind operation, int32 naffected)
++makeAnalyze(Oid relOid, CmdKind operation, int64 naffected)
  {
        TimestampTz                             now = GetCurrentTimestamp();
        Relation                                rel;
        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);
  
                        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) &&
 +              /* do not analyze too small tables */
 +              rstat->n_tuples + rstat->changes_since_analyze + naffected > online_analyze_lower_limit &&
                /* be in sync with relation_needs_vacanalyze */
                ((double)(rstat->changes_since_analyze + naffected)) >=
                         online_analyze_scale_factor * ((double)rstat->n_tuples) +
  
                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)
                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 */
@@@ -562,7 -615,7 +618,7 @@@ extern PGDLLIMPORT void onlineAnalyzeHo
  void
  onlineAnalyzeHooker(QueryDesc *queryDesc)
  {
 -      uint32  naffected = -1;
 +      int64   naffected = -1;
  
        if (queryDesc->estate)
                naffected = queryDesc->estate->es_processed;
                                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);
                        }
                }
        }
  
  #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
                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
@@@ -886,28 -988,6 +991,28 @@@ _PG_init(void
  #endif
                includeTablesShow
        );
 +
 +      DefineCustomIntVariable(
 +              "online_analyze.lower_limit",
 +              "min number of rows in table to analyze",
 +              "min number of rows in table to analyze",
 +              &online_analyze_lower_limit,
 +#if PG_VERSION_NUM >= 80400
 +              online_analyze_lower_limit,
 +#endif
 +              0,
 +              0x7fffffff,
 +              PGC_USERSET,
 +#if PG_VERSION_NUM >= 80400
 +              GUC_NOT_IN_SAMPLE,
 +#if PG_VERSION_NUM >= 90100
 +              NULL,
 +#endif
 +#endif
 +              NULL,
 +              NULL
 +      );
 +
  }
  
  void _PG_fini(void);