Hi,
I found that the enable_hashjoin disables HashJoin completely.
It's in the function add_paths_to_joinrel:
if (enable_hashjoin || jointype == JOIN_FULL)
hash_inner_and_outer(root, joinrel, outerrel, innerrel,
jointype, &extra);
Instead, it should add a disable cost to the cost calculation of
hashjoin. And now final_cost_hashjoin does the same thing:
if (!enable_hashjoin)
startup_cost += disable_cost;
enable_mergejoin has the same problem.
Test case:
CREATE TABLE t_score_01(
s_id int,
s_score int,
s_course char(8),
c_id int);
CREATE TABLE t_student_01(
s_id int,
s_name char(8));
insert into t_score_01 values(
generate_series(1, 1000000), random()*100, 'course', generate_series(1,
1000000));
insert into t_student_01 values(generate_series(1, 1000000), 'name');
analyze t_score_01;
analyze t_student_01;
SET enable_hashjoin TO off;
SET enable_nestloop TO off;
SET enable_mergejoin TO off;
explain select count(*)
from t_student_01 a join t_score_01 b on a.s_id=b.s_id;
After disabling all three, the HashJoin path should still be chosen.
Attached is the patch file.
--
Quan Zongliang
Vastdata
diff --git a/src/backend/optimizer/path/joinpath.c
b/src/backend/optimizer/path/joinpath.c
index bd51e4f972..4b5ab7f7ff 100644
--- a/src/backend/optimizer/path/joinpath.c
+++ b/src/backend/optimizer/path/joinpath.c
@@ -206,14 +206,13 @@ add_paths_to_joinrel(PlannerInfo *root,
* way of implementing a full outer join, so override enable_mergejoin
if
* it's a full join.
*/
- if (enable_mergejoin || jointype == JOIN_FULL)
- extra.mergeclause_list = select_mergejoin_clauses(root,
-
joinrel,
-
outerrel,
-
innerrel,
-
restrictlist,
-
jointype,
-
&mergejoin_allowed);
+ extra.mergeclause_list = select_mergejoin_clauses(root,
+
joinrel,
+
outerrel,
+
innerrel,
+
restrictlist,
+
jointype,
+
&mergejoin_allowed);
/*
* If it's SEMI, ANTI, or inner_unique join, compute correction factors
@@ -316,9 +315,8 @@ add_paths_to_joinrel(PlannerInfo *root,
* before being joined. As above, disregard enable_hashjoin for full
* joins, because there may be no other alternative.
*/
- if (enable_hashjoin || jointype == JOIN_FULL)
- hash_inner_and_outer(root, joinrel, outerrel, innerrel,
- jointype, &extra);
+ hash_inner_and_outer(root, joinrel, outerrel, innerrel,
+ jointype, &extra);
/*
* 5. If inner and outer relations are foreign tables (or joins)
belonging