Skip to content

Ability to enable/disable indexes through GUC #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions doc/src/sgml/config.sgml
Original file line number Diff line number Diff line change
Expand Up @@ -6375,6 +6375,24 @@ SELECT * FROM parent WHERE key = 2400;
</listitem>
</varlistentry>

<varlistentry id="guc-disabled-indexes" xreflabel="disabled_indexes">
<term><varname>disabled_indexes</varname> (<type>string</type>)
<indexterm>
<primary><varname>disabled_indexes</varname> configuration parameter</primary>
</indexterm>
</term>
<listitem>
<para>
Specifies a comma-separated list of index names that should be ignored
by the query planner. This allows for temporarily disabling specific
indexes without needing to drop them or rebuild them when enabling.
This can be useful for testing query performance with and without
certain indexes. It is a session-level parameter, allowing for easily managing
the list of disabled indexes.
</para>
</listitem>
</varlistentry>

</variablelist>
</sect2>
</sect1>
Expand Down
102 changes: 102 additions & 0 deletions src/backend/optimizer/util/plancat.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,18 @@
#include "storage/bufmgr.h"
#include "tcop/tcopprot.h"
#include "utils/builtins.h"
#include "utils/guc_hooks.h"
#include "utils/lsyscache.h"
#include "utils/partcache.h"
#include "utils/plancache.h"
#include "utils/rel.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
#include "utils/varlena.h"

/* GUC parameter */
int constraint_exclusion = CONSTRAINT_EXCLUSION_PARTITION;
char *disabled_indexes = "";

/* Hook for plugins to get control in get_relation_info() */
get_relation_info_hook_type get_relation_info_hook = NULL;
Expand Down Expand Up @@ -295,6 +299,21 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
info->opcintype = (Oid *) palloc(sizeof(Oid) * nkeycolumns);
info->canreturn = (bool *) palloc(sizeof(bool) * ncolumns);

/*
* Skip disabled indexes all together, as they should not be considered
* for query planning. This builds the data structure for the planner's
* use and we make it part of IndexOptInfo since the index is already open.
* We also free the memory and close the relation before continuing
* to the next index.
*/
info->isdisabled = is_index_disabled(RelationGetRelationName(indexRelation));
if (info->isdisabled)
{
pfree(info);
index_close(indexRelation, NoLock);
continue;
}

for (i = 0; i < ncolumns; i++)
{
info->indexkeys[i] = index->indkey.values[i];
Expand Down Expand Up @@ -2596,3 +2615,86 @@ set_baserel_partition_constraint(Relation relation, RelOptInfo *rel)
rel->partition_qual = partconstr;
}
}

/*
* is_index_disabled
* Checks if the given index is in the list of disabled indexes.
*/
bool
is_index_disabled(const char *indexName)
{
List *namelist;
ListCell *l;
char *rawstring;
bool result = false;

if (disabled_indexes == NULL || disabled_indexes[0] == '\0' || indexName == NULL)
return false;

rawstring = pstrdup(disabled_indexes);

if (!SplitIdentifierString(rawstring, ',', &namelist))
{
pfree(rawstring);
list_free(namelist);
return false;
}

foreach(l, namelist)
{
if (strcmp(indexName, (char *) lfirst(l)) == 0)
{
result = true;
break;
}
}

list_free(namelist);
pfree(rawstring);

return result;
}

/*
* assign_disabled_indexes
* GUC assign_hook for "disabled_indexes" GUC variable.
* Updates the disabled_indexes value and resets the plan cache if the value has changed.
*/
void
assign_disabled_indexes(const char *newval, void *extra)
{
if (disabled_indexes == NULL || strcmp(disabled_indexes, newval) != 0)
{
disabled_indexes = guc_strdup(ERROR, newval);
ResetPlanCache();
}
}

/*
* check_disabled_indexes
* GUC check_hook for "disabled_indexes" GUC variable.
* Validates the new value for disabled_indexes.
*/
bool
check_disabled_indexes(char **newval, void **extra, GucSource source)
{
List *namelist = NIL;
char *rawstring;

if (*newval == NULL || strcmp(*newval, "") == 0)
return true;

rawstring = pstrdup(*newval);

if (!SplitIdentifierString(rawstring, ',', &namelist))
{
pfree(rawstring);
list_free(namelist);
return false;
}

pfree(rawstring);
list_free(namelist);

return true;
}
12 changes: 12 additions & 0 deletions src/backend/utils/misc/guc_tables.c
Original file line number Diff line number Diff line change
Expand Up @@ -4783,6 +4783,18 @@ struct config_string ConfigureNamesString[] =
check_restrict_nonsystem_relation_kind, assign_restrict_nonsystem_relation_kind, NULL
},

{
{"disabled_indexes", PGC_USERSET, QUERY_TUNING_OTHER,
gettext_noop("Sets the list of indexes to be disabled for query planning."),
NULL,
GUC_LIST_INPUT | GUC_NOT_IN_SAMPLE | GUC_EXPLAIN
},
&disabled_indexes,
"",
check_disabled_indexes, assign_disabled_indexes, NULL
},


/* End-of-list marker */
{
{NULL, 0, 0, NULL, NULL}, NULL, NULL, NULL, NULL, NULL
Expand Down
2 changes: 2 additions & 0 deletions src/include/nodes/pathnodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -1207,6 +1207,8 @@ struct IndexOptInfo
/* AM's cost estimator */
/* Rather than include amapi.h here, we declare amcostestimate like this */
void (*amcostestimate) () pg_node_attr(read_write_ignore);
/* true if this index is asked to be disabled */
bool isdisabled;
};

/*
Expand Down
6 changes: 6 additions & 0 deletions src/include/optimizer/optimizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,4 +203,10 @@ extern List *pull_var_clause(Node *node, int flags);
extern Node *flatten_join_alias_vars(PlannerInfo *root, Query *query, Node *node);
extern Node *flatten_group_exprs(PlannerInfo *root, Query *query, Node *node);

/*
* GUC variable for specifying indexes to be ignored by the query planner.
* Contains a comma-separated list of index names.
*/
extern PGDLLIMPORT char *disabled_indexes;

#endif /* OPTIMIZER_H */
5 changes: 5 additions & 0 deletions src/include/utils/guc_hooks.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,4 +175,9 @@ extern bool check_synchronized_standby_slots(char **newval, void **extra,
GucSource source);
extern void assign_synchronized_standby_slots(const char *newval, void *extra);


extern void assign_disabled_indexes(const char *newval, void *extra);
extern bool is_index_disabled(const char *indexName);
extern bool check_disabled_indexes(char **newval, void **extra, GucSource source);

#endif /* GUC_HOOKS_H */
Loading