diff options
Diffstat (limited to 'src/backend/optimizer')
| -rw-r--r-- | src/backend/optimizer/plan/subselect.c | 45 | ||||
| -rw-r--r-- | src/backend/optimizer/util/pathnode.c | 12 |
2 files changed, 30 insertions, 27 deletions
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index 14192a13236..ff63d20f8d5 100644 --- a/src/backend/optimizer/plan/subselect.c +++ b/src/backend/optimizer/plan/subselect.c @@ -20,6 +20,7 @@ #include "catalog/pg_operator.h" #include "catalog/pg_type.h" #include "executor/executor.h" +#include "executor/nodeSubplan.h" #include "miscadmin.h" #include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" @@ -79,8 +80,8 @@ static Node *convert_testexpr(PlannerInfo *root, List *subst_nodes); static Node *convert_testexpr_mutator(Node *node, convert_testexpr_context *context); -static bool subplan_is_hashable(Plan *plan); -static bool subpath_is_hashable(Path *path); +static bool subplan_is_hashable(Plan *plan, bool unknownEqFalse); +static bool subpath_is_hashable(Path *path, bool unknownEqFalse); static bool testexpr_is_hashable(Node *testexpr, List *param_ids); static bool test_opexpr_is_hashable(OpExpr *testexpr, List *param_ids); static bool hash_ok_operator(OpExpr *expr); @@ -283,7 +284,7 @@ make_subplan(PlannerInfo *root, Query *orig_subquery, best_path = final_rel->cheapest_total_path; /* Now we can check if it'll fit in hash_mem */ - if (subpath_is_hashable(best_path)) + if (subpath_is_hashable(best_path, true)) { SubPlan *hashplan; AlternativeSubPlan *asplan; @@ -524,7 +525,7 @@ build_subplan(PlannerInfo *root, Plan *plan, Path *path, */ if (subLinkType == ANY_SUBLINK && splan->parParam == NIL && - subplan_is_hashable(plan) && + subplan_is_hashable(plan, unknownEqFalse) && testexpr_is_hashable(splan->testexpr, splan->paramIds)) splan->useHashTable = true; @@ -711,19 +712,19 @@ convert_testexpr_mutator(Node *node, * is suitable for hashing. We only look at the subquery itself. */ static bool -subplan_is_hashable(Plan *plan) +subplan_is_hashable(Plan *plan, bool unknownEqFalse) { - double subquery_size; + Size hashtablesize; /* - * The estimated size of the subquery result must fit in hash_mem. (Note: - * we use heap tuple overhead here even though the tuples will actually be - * stored as MinimalTuples; this provides some fudge factor for hashtable - * overhead.) + * The estimated size of the hashtable holding the subquery result must + * fit in hash_mem. (Note: reject on equality, to ensure that an estimate + * of SIZE_MAX disables hashing regardless of the hash_mem limit.) */ - subquery_size = plan->plan_rows * - (MAXALIGN(plan->plan_width) + MAXALIGN(SizeofHeapTupleHeader)); - if (subquery_size > get_hash_memory_limit()) + hashtablesize = EstimateSubplanHashTableSpace(plan->plan_rows, + plan->plan_width, + unknownEqFalse); + if (hashtablesize >= get_hash_memory_limit()) return false; return true; @@ -735,19 +736,19 @@ subplan_is_hashable(Plan *plan) * Identical to subplan_is_hashable, but work from a Path for the subplan. */ static bool -subpath_is_hashable(Path *path) +subpath_is_hashable(Path *path, bool unknownEqFalse) { - double subquery_size; + Size hashtablesize; /* - * The estimated size of the subquery result must fit in hash_mem. (Note: - * we use heap tuple overhead here even though the tuples will actually be - * stored as MinimalTuples; this provides some fudge factor for hashtable - * overhead.) + * The estimated size of the hashtable holding the subquery result must + * fit in hash_mem. (Note: reject on equality, to ensure that an estimate + * of SIZE_MAX disables hashing regardless of the hash_mem limit.) */ - subquery_size = path->rows * - (MAXALIGN(path->pathtarget->width) + MAXALIGN(SizeofHeapTupleHeader)); - if (subquery_size > get_hash_memory_limit()) + hashtablesize = EstimateSubplanHashTableSpace(path->rows, + path->pathtarget->width, + unknownEqFalse); + if (hashtablesize >= get_hash_memory_limit()) return false; return true; diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c index 44ac5312edd..e4fd6950fad 100644 --- a/src/backend/optimizer/util/pathnode.c +++ b/src/backend/optimizer/util/pathnode.c @@ -17,6 +17,7 @@ #include <math.h> #include "access/htup_details.h" +#include "executor/nodeSetOp.h" #include "foreign/fdwapi.h" #include "miscadmin.h" #include "nodes/extensible.h" @@ -3461,7 +3462,7 @@ create_setop_path(PlannerInfo *root, } else { - Size hashentrysize; + Size hashtablesize; /* * In hashed mode, we must read all the input before we can emit @@ -3490,11 +3491,12 @@ create_setop_path(PlannerInfo *root, /* * Also disable if it doesn't look like the hashtable will fit into - * hash_mem. + * hash_mem. (Note: reject on equality, to ensure that an estimate of + * SIZE_MAX disables hashing regardless of the hash_mem limit.) */ - hashentrysize = MAXALIGN(leftpath->pathtarget->width) + - MAXALIGN(SizeofMinimalTupleHeader); - if (hashentrysize * numGroups > get_hash_memory_limit()) + hashtablesize = EstimateSetOpHashTableSpace(numGroups, + leftpath->pathtarget->width); + if (hashtablesize >= get_hash_memory_limit()) pathnode->path.disabled_nodes++; } pathnode->path.rows = outputRows; |
