X-Git-Url: http://sigaev.ru/git/gitweb.cgi?p=plantuner.git;a=blobdiff_plain;f=plantuner.c;h=96d679ac60008e931f9ca7089a98605d9c123cd8;hp=4e0f0c598b2abca7b9b933bd9427b528affb3f77;hb=a07b2ca58b6804b8a261e674a159eb442362471a;hpb=176da910e8225a413bac8992e650507f10f9b9d1 diff --git a/plantuner.c b/plantuner.c index 4e0f0c5..96d679a 100644 --- a/plantuner.c +++ b/plantuner.c @@ -1,23 +1,52 @@ /* * Copyright (c) 2009 Teodor Sigaev + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY CONTRIBUTORS ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include +#include #include #include #include #include +#include #include #include #include +#include PG_MODULE_MAGIC; static int nIndexesOut = 0; static Oid *indexesOut = NULL; get_relation_info_hook_type prevHook = NULL; +static bool fix_empty_table = false; static char *indexesOutStr = ""; @@ -41,7 +70,7 @@ 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) @@ -51,12 +80,18 @@ indexesOutAssign(const char * newval, bool doit, GucSource source) 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) @@ -84,6 +119,30 @@ cleanup: return NULL; } +#if PG_VERSION_NUM >= 90100 + +static bool +indexesOutCheck(char **newval, void **extra, GucSource source) +{ + char *val; + + val = (char*)indexesOutAssign(*newval, false, source); + + if (val) + { + *newval = val; + return true; + } + + return false; +} +static void +indexesOutAssignNew(const char *newval, void *extra) +{ + indexesOutAssign(newval, true, PGC_S_USER /* doesn't matter */); +} + +#endif static void indexFilter(PlannerInfo *root, Oid relationObjectId, bool inhparent, RelOptInfo *rel) { @@ -105,6 +164,35 @@ indexFilter(PlannerInfo *root, Oid relationObjectId, bool inhparent, RelOptInfo } } + 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 */ @@ -153,13 +241,37 @@ _PG_init(void) "", PGC_USERSET, 0, +#if PG_VERSION_NUM >= 90100 + indexesOutCheck, + indexesOutAssignNew, +#else indexesOutAssign, +#endif IndexFilterShow ); - if (get_relation_info_hook != indexFilter ) + 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 != execPlantuner ) { prevHook = get_relation_info_hook; - get_relation_info_hook = indexFilter; + get_relation_info_hook = execPlantuner; } }