X-Git-Url: http://sigaev.ru/git/gitweb.cgi?p=plantuner.git;a=blobdiff_plain;f=plantuner.c;h=02b710193a4823a42e45e0df72f1adc4d44ab106;hp=bf3c511b0c923a0307f3202bd2e24add7973a1e2;hb=f848282efaa855fb8da0db07520cc656d83a047f;hpb=4658687fa586302f46026d1405b36a3fdac87612 diff --git a/plantuner.c b/plantuner.c index bf3c511..02b7101 100644 --- a/plantuner.c +++ b/plantuner.c @@ -30,24 +30,33 @@ #include #include +#include #include #include #include #include +#include #include #include #include +#include PG_MODULE_MAGIC; -static int nIndexesOut = 0; -static Oid *indexesOut = NULL; +static int nDisabledIndexes = 0; +static Oid *disabledIndexes = NULL; +static char *disableIndexesOutStr = ""; + +static int nEnabledIndexes = 0; +static Oid *enabledIndexes = NULL; +static char *enableIndexesOutStr = ""; + get_relation_info_hook_type prevHook = NULL; +static bool fix_empty_table = false; -static char *indexesOutStr = ""; static const char * -indexesOutAssign(const char * newval, bool doit, GucSource source) +indexesAssign(const char * newval, bool doit, GucSource source, bool isDisable) { char *rawname; List *namelist; @@ -66,22 +75,34 @@ indexesOutAssign(const char * newval, bool doit, GucSource source) nOids = list_length(namelist); newOids = malloc(sizeof(Oid) * (nOids+1)); if (!newOids) - elog(ERROR,"could not allocate %d bytes", sizeof(Oid) * (nOids+1)); + elog(ERROR,"could not allocate %d bytes", (int)(sizeof(Oid) * (nOids+1))); } foreach(l, namelist) { char *curname = (char *) lfirst(l); - Oid indexOid = RangeVarGetRelid(makeRangeVarFromNameList(stringToQualifiedNameList(curname)), true); +#if PG_VERSION_NUM >= 90200 + Oid indexOid = RangeVarGetRelid(makeRangeVarFromNameList(stringToQualifiedNameList(curname)), + NoLock, true); +#else + Oid indexOid = RangeVarGetRelid(makeRangeVarFromNameList(stringToQualifiedNameList(curname)), + true); +#endif if (indexOid == InvalidOid) { - elog(WARNING,"'%s' does not exist", curname); +#if PG_VERSION_NUM >= 90100 + if (doit == false) +#endif + elog(WARNING,"'%s' does not exist", curname); continue; } else if ( get_rel_relkind(indexOid) != RELKIND_INDEX ) { - elog(WARNING,"'%s' is not an index", curname); +#if PG_VERSION_NUM >= 90100 + if (doit == false) +#endif + elog(WARNING,"'%s' is not an index", curname); continue; } else if (doit) @@ -92,8 +113,16 @@ indexesOutAssign(const char * newval, bool doit, GucSource source) if (doit) { - nIndexesOut = nOids; - indexesOut = newOids; + if (isDisable) + { + nDisabledIndexes = nOids; + disabledIndexes = newOids; + } + else + { + nEnabledIndexes = nOids; + enabledIndexes = newOids; + } } pfree(rawname); @@ -109,12 +138,71 @@ cleanup: return NULL; } +static const char * +assignDisabledIndexes(const char * newval, bool doit, GucSource source) +{ + return indexesAssign(newval, doit, source, true); +} + +static const char * +assignEnabledIndexes(const char * newval, bool doit, GucSource source) +{ + return indexesAssign(newval, doit, source, false); +} + +#if PG_VERSION_NUM >= 90100 + +static bool +checkDisabledIndexes(char **newval, void **extra, GucSource source) +{ + char *val; + + val = (char*)indexesAssign(*newval, false, source, true); + + if (val) + { + *newval = val; + return true; + } + + return false; +} + +static bool +checkEnabledIndexes(char **newval, void **extra, GucSource source) +{ + char *val; + + val = (char*)indexesAssign(*newval, false, source, false); + + if (val) + { + *newval = val; + return true; + } + + return false; +} + +static void +assignDisabledIndexesNew(const char *newval, void *extra) +{ + assignDisabledIndexes(newval, true, PGC_S_USER /* doesn't matter */); +} + +static void +assignEnabledIndexesNew(const char *newval, void *extra) +{ + assignEnabledIndexes(newval, true, PGC_S_USER /* doesn't matter */); +} + +#endif static void indexFilter(PlannerInfo *root, Oid relationObjectId, bool inhparent, RelOptInfo *rel) { int i; - for(i=0;iindexoid) + if (disabledIndexes[i] == info->indexoid) { - rel->indexlist = list_delete_ptr(rel->indexlist, info); + int j; + + for(j=0; jindexoid) + break; + + if (j >= nEnabledIndexes) + rel->indexlist = list_delete_ptr(rel->indexlist, info); + break; } } } + if (fix_empty_table && rel) + { + + + } + +} + +static void +execPlantuner(PlannerInfo *root, Oid relationObjectId, bool inhparent, RelOptInfo *rel) { + Relation relation; + + relation = heap_open(relationObjectId, NoLock); + if (relation->rd_rel->relkind == RELKIND_RELATION) + { + if (fix_empty_table && RelationGetNumberOfBlocks(relation) == 0) + { + /* + * estimate_rel_size() could be too pessimistic for particular + * workload + */ + rel->pages = 0.0; + rel->tuples = 0.0; + } + + indexFilter(root, relationObjectId, inhparent, rel); + } + heap_close(relation, NoLock); + /* * Call next hook if it exists */ @@ -138,20 +263,20 @@ indexFilter(PlannerInfo *root, Oid relationObjectId, bool inhparent, RelOptInfo } static const char* -IndexFilterShow(void) +IndexFilterShow(Oid* indexes, int nIndexes) { char *val, *ptr; int i, len; - len = 1 /* \0 */ + nIndexesOut * (2 * NAMEDATALEN + 2 /* ', ' */ + 1 /* . */); + len = 1 /* \0 */ + nIndexes * (2 * NAMEDATALEN + 2 /* ', ' */ + 1 /* . */); ptr = val = palloc(len); - *ptr ='\0'; - for(i=0; i= 90100 + checkDisabledIndexes, + assignDisabledIndexesNew, +#else + assignDisabledIndexes, +#endif + disabledIndexFilterShow + ); + + DefineCustomStringVariable( + "plantuner.disable_index", + "List of disabled indexes", "Listed indexes will not be used in queries", - &indexesOutStr, + &disableIndexesOutStr, "", PGC_USERSET, 0, - indexesOutAssign, - IndexFilterShow +#if PG_VERSION_NUM >= 90100 + checkDisabledIndexes, + assignDisabledIndexesNew, +#else + assignDisabledIndexes, +#endif + disabledIndexFilterShow + ); + + DefineCustomStringVariable( + "plantuner.enable_index", + "List of enabled indexes (overload plantuner.disable_index)", + "Listed indexes which could be used in queries even they are listed in plantuner.disable_index", + &enableIndexesOutStr, + "", + PGC_USERSET, + 0, +#if PG_VERSION_NUM >= 90100 + checkEnabledIndexes, + assignEnabledIndexesNew, +#else + assignEnabledIndexes, +#endif + enabledIndexFilterShow + ); + + DefineCustomBoolVariable( + "plantuner.fix_empty_table", + "Sets to zero estimations for empty tables", + "Sets to zero estimations for empty or newly created tables", + &fix_empty_table, +#if PG_VERSION_NUM >= 80400 + fix_empty_table, +#endif + PGC_USERSET, +#if PG_VERSION_NUM >= 80400 + GUC_NOT_IN_SAMPLE, +#if PG_VERSION_NUM >= 90100 + NULL, +#endif +#endif + NULL, + NULL ); - if (get_relation_info_hook != indexFilter ) + if (get_relation_info_hook != execPlantuner ) { prevHook = get_relation_info_hook; - get_relation_info_hook = indexFilter; + get_relation_info_hook = execPlantuner; } }