static bool online_analyze_verbose = true;
static double online_analyze_scale_factor = 0.1;
static int online_analyze_threshold = 50;
+static int online_analyze_capacity_threshold = 100000;
static double online_analyze_min_interval = 10000;
static ExecutorEnd_hook_type oldExecutorEndHook = NULL;
TimestampTz analyze_timestamp;
} OnlineAnalyzeTableStat;
+static MemoryContext onlineAnalyzeMemoryContext = NULL;
static HTAB *relstats = NULL;
+static void relstatsInit();
+
static int
oid_cmp(const void *a, const void *b)
{
TimestampTz now = GetCurrentTimestamp();
Relation rel;
OnlineAnalyzeTableType reltype;
- bool found,
+ bool found = false,
newTable = false;
- OnlineAnalyzeTableStat *rstat;
+ OnlineAnalyzeTableStat *rstat,
+ dummyrstat;
PgStat_StatTabEntry *tabentry = NULL;
if (relOid == InvalidOid)
return;
if (naffected == 0)
- /* return if there is not changes */
+ /* return if there is no changes */
return;
else if (naffected < 0)
/* number if affected rows is unknown */
break;
}
- rstat = hash_search(relstats, &relOid, HASH_ENTER, &found);
+ /*
+ * Do not store data about persistent table in local memory because we
+ * could not track changes of them: they could be changed by another
+ * backends. So always get a pgstat table entry.
+ */
+ if (reltype == OATT_TEMPORARY)
+ rstat = hash_search(relstats, &relOid, HASH_ENTER, &found);
+ else
+ rstat = &dummyrstat; /* found == false for following if */
if (found == false || rstat->rereadStat == true || naffected == 0)
{
/* update last analyze timestamp in local memory of backend */
if (tabentry)
+ {
tabentry->analyze_timestamp = now;
-
+ tabentry->changes_since_analyze = 0;
+ }
#if 0
/* force reload stat for new table */
if (newTable)
else
{
#if PG_VERSION_NUM >= 90000
- if (tabentry != NULL)
+ if (tabentry)
tabentry->changes_since_analyze += naffected;
#endif
rstat->changes_since_analyze += naffected;
}
+
+ /* Reset local cache if we are over limit */
+ if (hash_get_num_entries(relstats) > online_analyze_capacity_threshold)
+ relstatsInit();
}
extern PGDLLIMPORT void onlineAnalyzeHooker(QueryDesc *queryDesc);
hash_ctl.hash = oid_hash;
flags |= HASH_FUNCTION;
+ if (onlineAnalyzeMemoryContext)
+ {
+ Assert(relstats != NULL);
+ MemoryContextReset(onlineAnalyzeMemoryContext);
+ }
+ else
+ {
+ Assert(relstats == NULL);
+ onlineAnalyzeMemoryContext =
+ AllocSetContextCreate(CacheMemoryContext,
+ "online_analyze storage context",
+ ALLOCSET_DEFAULT_SIZES);
+ }
+
hash_ctl.hcxt = AllocSetContextCreate(CacheMemoryContext,
"online_analyze storage context",
ALLOCSET_DEFAULT_SIZES);
NULL
);
+ DefineCustomIntVariable(
+ "online_analyze.capacity_threshold",
+ "Max local cache table capacity",
+ "Max local cache table capacity",
+ &online_analyze_capacity_threshold,
+#if PG_VERSION_NUM >= 80400
+ online_analyze_capacity_threshold,
+#endif
+ 0,
+ 0x7fffffff,
+ PGC_USERSET,
+#if PG_VERSION_NUM >= 80400
+ GUC_NOT_IN_SAMPLE,
+#if PG_VERSION_NUM >= 90100
+ NULL,
+#endif
+#endif
+ NULL,
+ NULL
+ );
+
DefineCustomRealVariable(
"online_analyze.min_interval",
"minimum time interval between analyze call (in milliseconds)",