diff options
Diffstat (limited to 'src/backend/optimizer/path/indxpath.c')
| -rw-r--r-- | src/backend/optimizer/path/indxpath.c | 32 | 
1 files changed, 31 insertions, 1 deletions
| diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index f295558f767..5f464153942 100644 --- a/src/backend/optimizer/path/indxpath.c +++ b/src/backend/optimizer/path/indxpath.c @@ -67,6 +67,7 @@ typedef struct  	List	   *quals;			/* the WHERE clauses it uses */  	List	   *preds;			/* predicates of its partial index(es) */  	Bitmapset  *clauseids;		/* quals+preds represented as a bitmapset */ +	bool		unclassifiable; /* has too many quals+preds to process? */  } PathClauseUsage;  /* Callback argument for ec_member_matches_indexcol */ @@ -1447,9 +1448,18 @@ choose_bitmap_and(PlannerInfo *root, RelOptInfo *rel, List *paths)  		Path	   *ipath = (Path *) lfirst(l);  		pathinfo = classify_index_clause_usage(ipath, &clauselist); + +		/* If it's unclassifiable, treat it as distinct from all others */ +		if (pathinfo->unclassifiable) +		{ +			pathinfoarray[npaths++] = pathinfo; +			continue; +		} +  		for (i = 0; i < npaths; i++)  		{ -			if (bms_equal(pathinfo->clauseids, pathinfoarray[i]->clauseids)) +			if (!pathinfoarray[i]->unclassifiable && +				bms_equal(pathinfo->clauseids, pathinfoarray[i]->clauseids))  				break;  		}  		if (i < npaths) @@ -1484,6 +1494,10 @@ choose_bitmap_and(PlannerInfo *root, RelOptInfo *rel, List *paths)  	 * For each surviving index, consider it as an "AND group leader", and see  	 * whether adding on any of the later indexes results in an AND path with  	 * cheaper total cost than before.  Then take the cheapest AND group. +	 * +	 * Note: paths that are either clauseless or unclassifiable will have +	 * empty clauseids, so that they will not be rejected by the clauseids +	 * filter here, nor will they cause later paths to be rejected by it.  	 */  	for (i = 0; i < npaths; i++)  	{ @@ -1711,6 +1725,21 @@ classify_index_clause_usage(Path *path, List **clauselist)  	result->preds = NIL;  	find_indexpath_quals(path, &result->quals, &result->preds); +	/* +	 * Some machine-generated queries have outlandish numbers of qual clauses. +	 * To avoid getting into O(N^2) behavior even in this preliminary +	 * classification step, we want to limit the number of entries we can +	 * accumulate in *clauselist.  Treat any path with more than 100 quals + +	 * preds as unclassifiable, which will cause calling code to consider it +	 * distinct from all other paths. +	 */ +	if (list_length(result->quals) + list_length(result->preds) > 100) +	{ +		result->clauseids = NULL; +		result->unclassifiable = true; +		return result; +	} +  	/* Build up a bitmapset representing the quals and preds */  	clauseids = NULL;  	foreach(lc, result->quals) @@ -1728,6 +1757,7 @@ classify_index_clause_usage(Path *path, List **clauselist)  								   find_list_position(node, clauselist));  	}  	result->clauseids = clauseids; +	result->unclassifiable = false;  	return result;  } | 
