Skip to content

Commit 7f3ec69

Browse files
Dousir9BohuTANG
andauthored
chore(planner): improve physical join (#16962)
* chore(planner): improve physical join * chore(test): add sqllogictest * chore(code): refine comments. * chore(test): update sqllogictest * chore(test): test iceberg * chore(test): test iceberg * chore(planner): fix join type * chore(test): update sqllogictest * chore(test): update sqllogictest --------- Co-authored-by: Bohu <overred.shuttler@gmail.com>
1 parent 25d615f commit 7f3ec69

File tree

4 files changed

+109
-8
lines changed

4 files changed

+109
-8
lines changed

src/query/sql/src/executor/physical_plans/physical_join.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,21 @@ pub fn physical_join(join: &Join, s_expr: &SExpr) -> Result<PhysicalJoinType> {
4646
return Ok(PhysicalJoinType::Hash);
4747
}
4848

49-
let left_prop = RelExpr::with_s_expr(s_expr.child(1)?).derive_relational_prop()?;
50-
let right_prop = RelExpr::with_s_expr(s_expr.child(0)?).derive_relational_prop()?;
49+
let left_rel_expr = RelExpr::with_s_expr(s_expr.child(0)?);
50+
let right_rel_expr = RelExpr::with_s_expr(s_expr.child(1)?);
51+
if matches!(
52+
right_rel_expr
53+
.derive_cardinality()?
54+
.statistics
55+
.precise_cardinality,
56+
Some(1)
57+
) {
58+
// If the output rows of build side is equal to 1, we use CROSS JOIN + FILTER instead of MERGE JOIN.
59+
return Ok(PhysicalJoinType::Hash);
60+
}
61+
62+
let left_prop = left_rel_expr.derive_relational_prop()?;
63+
let right_prop = right_rel_expr.derive_relational_prop()?;
5164
let mut range_conditions = vec![];
5265
let mut other_conditions = vec![];
5366
for condition in join.non_equi_conditions.iter() {

tests/sqllogictests/suites/mode/standalone/explain/join.test

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -940,3 +940,47 @@ EvalScalar
940940

941941
statement ok
942942
drop table t1;
943+
944+
statement ok
945+
CREATE OR REPLACE TABLE t1(a INT);
946+
947+
statement ok
948+
CREATE OR REPLACE TABLE t2(a INT);
949+
950+
statement ok
951+
INSERT INTO t1 VALUES(1), (2), (3), (4);
952+
953+
statement ok
954+
INSERT INTO t2 VALUES(1);
955+
956+
query T
957+
EXPLAIN SELECT * FROM t1 WHERE a >= (SELECT MAX(a) FROM t2);
958+
----
959+
HashJoin
960+
├── output columns: [t1.a (#0)]
961+
├── join type: INNER
962+
├── build keys: []
963+
├── probe keys: []
964+
├── filters: [t1.a (#0) >= CAST(scalar_subquery_2 (#2) AS Int32 NULL)]
965+
├── estimated rows: 4.00
966+
├── EvalScalar(Build)
967+
│ ├── output columns: [MAX(a) (#2)]
968+
│ ├── expressions: [1]
969+
│ ├── estimated rows: 1.00
970+
│ └── DummyTableScan
971+
└── TableScan(Probe)
972+
├── table: default.default.t1
973+
├── output columns: [a (#0)]
974+
├── read rows: 4
975+
├── read size: < 1 KiB
976+
├── partitions total: 1
977+
├── partitions scanned: 1
978+
├── pruning stats: [segments: <range pruning: 1 to 1>, blocks: <range pruning: 1 to 1>]
979+
├── push downs: [filters: [], limit: NONE]
980+
└── estimated rows: 4.00
981+
982+
statement ok
983+
DROP TABLE t1;
984+
985+
statement ok
986+
DROP TABLE t2;

tests/sqllogictests/suites/mode/standalone/explain_native/join.test

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,3 +634,47 @@ set enable_cbo = 1
634634

635635
statement ok
636636
drop table t1
637+
638+
statement ok
639+
CREATE OR REPLACE TABLE t1(a INT);
640+
641+
statement ok
642+
CREATE OR REPLACE TABLE t2(a INT);
643+
644+
statement ok
645+
INSERT INTO t1 VALUES(1), (2), (3), (4);
646+
647+
statement ok
648+
INSERT INTO t2 VALUES(1);
649+
650+
query T
651+
EXPLAIN SELECT * FROM t1 WHERE a >= (SELECT MAX(a) FROM t2);
652+
----
653+
HashJoin
654+
├── output columns: [t1.a (#0)]
655+
├── join type: INNER
656+
├── build keys: []
657+
├── probe keys: []
658+
├── filters: [t1.a (#0) >= CAST(scalar_subquery_2 (#2) AS Int32 NULL)]
659+
├── estimated rows: 4.00
660+
├── EvalScalar(Build)
661+
│ ├── output columns: [MAX(a) (#2)]
662+
│ ├── expressions: [1]
663+
│ ├── estimated rows: 1.00
664+
│ └── DummyTableScan
665+
└── TableScan(Probe)
666+
├── table: default.default.t1
667+
├── output columns: [a (#0)]
668+
├── read rows: 4
669+
├── read size: < 1 KiB
670+
├── partitions total: 1
671+
├── partitions scanned: 1
672+
├── pruning stats: [segments: <range pruning: 1 to 1>, blocks: <range pruning: 1 to 1>]
673+
├── push downs: [filters: [], limit: NONE]
674+
└── estimated rows: 4.00
675+
676+
statement ok
677+
DROP TABLE t1;
678+
679+
statement ok
680+
DROP TABLE t2;

tests/sqllogictests/suites/tpch/join_order.test

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -532,8 +532,8 @@ group by
532532
order by
533533
value desc limit 100;
534534
----
535-
RangeJoin: INNER
536-
├── Left
535+
HashJoin: INNER
536+
├── Build
537537
│ └── HashJoin: INNER
538538
│ ├── Build
539539
│ │ └── HashJoin: INNER
@@ -543,7 +543,7 @@ RangeJoin: INNER
543543
│ │ └── Scan: default.tpch_test.supplier (#4) (read rows: 1000)
544544
│ └── Probe
545545
│ └── Scan: default.tpch_test.partsupp (#3) (read rows: 80000)
546-
└── Right
546+
└── Probe
547547
└── HashJoin: INNER
548548
├── Build
549549
│ └── HashJoin: INNER
@@ -1104,10 +1104,10 @@ order by
11041104
----
11051105
HashJoin: RIGHT ANTI
11061106
├── Build
1107-
│ └── RangeJoin: INNER
1108-
│ ├── Left
1107+
│ └── HashJoin: INNER
1108+
│ ├── Build
11091109
│ │ └── Scan: default.tpch_test.customer (#1) (read rows: 15000)
1110-
│ └── Right
1110+
│ └── Probe
11111111
│ └── Scan: default.tpch_test.customer (#0) (read rows: 15000)
11121112
└── Probe
11131113
└── Scan: default.tpch_test.orders (#2) (read rows: 150000)

0 commit comments

Comments
 (0)