#include "postgres.h"
#include "pgstat.h"
+#include "access/transam.h"
#include "catalog/namespace.h"
#include "commands/vacuum.h"
#include "executor/executor.h"
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
#endif
static void
-makeAnalyze(Oid relOid, CmdKind operation, int32 naffected)
+makeAnalyze(Oid relOid, CmdKind operation, int64 naffected)
{
TimestampTz now = GetCurrentTimestamp();
Relation rel;
Assert(rstat->tableid == relOid);
+ elog(NOTICE,"makeAnalyze op:%d %u", operation, naffected);
+
if (operation != CK_TRUNCATE &&
(found == false || rstat->rereadStat == true))
{
}
}
- 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) +
{
case CK_INSERT:
rstat->n_tuples += naffected;
+ rstat->rereadStat = false;
break;
case CK_UPDATE:
rstat->n_tuples += naffected;
break;
case CK_TRUNCATE:
rstat->n_tuples = 0;
+ rstat->rereadStat = false;
break;
default:
break;
rstat->changes_since_analyze += naffected;
break;
case CK_TRUNCATE:
- rstat->changes_since_analyze = rstat->n_tuples;
+ rstat->changes_since_analyze = 0;
rstat->n_tuples = 0;
break;
default:
relstatsInit();
}
+static Const*
+isFastTruncateCall(QueryDesc *queryDesc)
+{
+ TargetEntry *te;
+ FuncExpr *fe;
+ Const *constval;
+
+ if (!(
+ queryDesc->plannedstmt &&
+ queryDesc->operation == CMD_SELECT &&
+ queryDesc->plannedstmt->planTree &&
+ queryDesc->plannedstmt->planTree->targetlist &&
+ list_length(queryDesc->plannedstmt->planTree->targetlist) == 1 &&
+ IsA(linitial(queryDesc->plannedstmt->planTree->targetlist), TargetEntry)
+ ))
+ return NULL;
+
+ te = linitial(queryDesc->plannedstmt->planTree->targetlist);
+
+ if (!IsA(te, TargetEntry))
+ return NULL;
+
+ fe = (FuncExpr*)te->expr;
+
+ if (!(
+ fe && IsA(fe, FuncExpr) &&
+ fe->funcid >= FirstNormalObjectId &&
+ fe->funcretset == false &&
+ fe->funcresulttype == VOIDOID &&
+ fe->funcvariadic == false &&
+ list_length(fe->args) == 1 &&
+ IsA(linitial(fe->args), Const)
+ ))
+ return NULL;
+
+ constval = linitial(fe->args);
+
+ if (!(
+ IsA(constval,Const) &&
+ constval->consttype == TEXTOID &&
+ strcmp(get_func_name(fe->funcid), "fasttruncate") == 0
+ ))
+ return NULL;
+
+ return constval;
+}
+
+
+
extern PGDLLIMPORT void onlineAnalyzeHooker(QueryDesc *queryDesc);
void
onlineAnalyzeHooker(QueryDesc *queryDesc)
{
- uint32 naffected = -1;
+ int64 naffected = -1;
+ Const *constval;
if (queryDesc->estate)
naffected = queryDesc->estate->es_processed;
+ if (online_analyze_enable &&
+ (constval = isFastTruncateCall(queryDesc)) != NULL)
+ {
+ Datum tblnamed = constval->constvalue;
+ char *tblname = text_to_cstring(DatumGetTextP(tblnamed));
+ RangeVar *tblvar =
+ makeRangeVarFromNameList(stringToQualifiedNameList(tblname));
+
+ makeAnalyze(RangeVarGetRelid(tblvar,
+#if PG_VERSION_NUM >= 90200
+ NoLock,
+#endif
+ false),
+ CK_TRUNCATE, -1);
+ }
+
if (online_analyze_enable && queryDesc->plannedstmt &&
(queryDesc->operation == CMD_INSERT ||
queryDesc->operation == CMD_UPDATE ||
#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);