Skip to content

Commit

Permalink
Merge pull request #79504 from mgartner/backport22.1-79389
Browse files Browse the repository at this point in the history
release-22.1: opt: do not generate unnecessary cross-joins on join input
  • Loading branch information
mgartner authored Apr 6, 2022
2 parents 4e8acc1 + 9c12570 commit 9b51fc1
Show file tree
Hide file tree
Showing 9 changed files with 242 additions and 172 deletions.
14 changes: 12 additions & 2 deletions pkg/sql/logictest/testdata/logic_test/inverted_join_multi_column
Original file line number Diff line number Diff line change
Expand Up @@ -494,8 +494,8 @@ ORDER BY (lk, rk)
5 12
5 16

# Regression test for #59615. Ensure that invalid inverted joins are not created
# for left and anti joins.
# Regression test for #59615 and #78681. Ensure that invalid inverted joins are
# not created for left, semi, and anti joins.
statement ok
CREATE TABLE t59615_inv (
x INT NOT NULL CHECK (x in (1, 3)),
Expand All @@ -517,3 +517,13 @@ SELECT * FROM (VALUES ('"a"'::jsonb), ('"b"'::jsonb)) AS u(y) WHERE NOT EXISTS (
----
"a"
"b"

statement ok
INSERT INTO t59615_inv VALUES (1, '"a"'::JSONB), (3, '"a"'::JSONB)

query T rowsort
SELECT * FROM (VALUES ('"a"'::jsonb), ('"b"'::jsonb)) AS u(y) WHERE EXISTS (
SELECT * FROM t59615_inv t WHERE t.y @> u.y
)
----
"a"
28 changes: 28 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/lookup_join
Original file line number Diff line number Diff line change
Expand Up @@ -665,3 +665,31 @@ SELECT * FROM (VALUES (1, 10), (2, 20), (3, NULL)) AS u(w, x) WHERE NOT EXISTS (
)
----
3 NULL

# Regression test for #79384. Do not generate unnecessary cross-joins on a
# lookup join's input when the lookup join uses a lookup expression.
statement ok
CREATE TABLE t79384a (
k INT NOT NULL
)

statement ok
CREATE TABLE t79384b (
a INT,
b INT,
c INT,
INDEX (a, b, c)
)

statement ok
INSERT INTO t79384a VALUES (1)

statement ok
INSERT INTO t79384b VALUES (1, 1, 1)

# The joined tables have a single row each, so this query should never return
# more than one row.
query I
SELECT k FROM t79384a INNER LOOKUP JOIN t79384b ON k = a AND b IN (1, 2, 3) AND c > 0
----
1
12 changes: 5 additions & 7 deletions pkg/sql/opt/exec/execbuilder/testdata/lookup_join_spans
Original file line number Diff line number Diff line change
Expand Up @@ -837,16 +837,14 @@ vectorized: true
│ equality cols are key
└── • lookup join
│ estimated row count: 0
│ table: metric_values@secondary
│ lookup condition: ((metric_id = id) AND (nullable = 1)) AND ("time" < '2020-01-01 00:00:10+00:00')
└── • render
│ estimated row count: 1
└── • scan
estimated row count: 1 (10% of the table; stats collected <hidden> ago)
table: metrics@name_index
spans: [/'cpu' - /'cpu']
└── • scan
estimated row count: 1 (10% of the table; stats collected <hidden> ago)
table: metrics@name_index
spans: [/'cpu' - /'cpu']


# Regression test for issue #68200. This ensures that we properly construct the
Expand Down
19 changes: 13 additions & 6 deletions pkg/sql/opt/xform/join_funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@ func (c *CustomFuncs) generateLookupJoinsImpl(
// because constructing a cross join with foundVals will
// increase the size of the input. As a result, non-matching
// input rows will show up more than once in the output,
// which is incorrect (see #59615 and #78685).
// which is incorrect (see #59615 and #78681).
shouldBuildMultiSpanLookupJoin = true
break
}
Expand Down Expand Up @@ -534,6 +534,9 @@ func (c *CustomFuncs) generateLookupJoinsImpl(

// Reset KeyCols since we're not using it anymore.
lookupJoin.KeyCols = opt.ColList{}
// Reset input since we don't need any constant values that may have
// been joined on the input above.
lookupJoin.Input = input
}

if len(lookupJoin.KeyCols) == 0 && len(lookupJoin.LookupExpr) == 0 {
Expand Down Expand Up @@ -1029,11 +1032,15 @@ func (c *CustomFuncs) GenerateInvertedJoins(
return
}

if len(foundVals) > 1 && (joinType == opt.LeftJoinOp || joinType == opt.AntiJoinOp) {
// We cannot create an inverted join in this case, because constructing
// a cross join with foundVals will increase the size of the input. As a
// result, non-matching input rows will show up more than once in the
// output, which is incorrect (see #59615).
if len(foundVals) > 1 &&
(joinType == opt.LeftJoinOp || joinType == opt.SemiJoinOp || joinType == opt.AntiJoinOp) {
// We cannot create an inverted join in this case, because
// constructing a cross join with foundVals will increase the
// size of the input. As a result, matching input rows will show
// up more than once in the output of a semi-join, and
// non-matching input rows will show up more than once in the
// output of a left or anti join, which is incorrect (see #59615
// and #78681).
// TODO(rytaft,mgartner): find a way to create an inverted join for this
// case.
return
Expand Down
77 changes: 33 additions & 44 deletions pkg/sql/opt/xform/testdata/external/tpce
Original file line number Diff line number Diff line change
Expand Up @@ -4029,34 +4029,31 @@ project
│ │ ├── fd: ()-->(1,8,27,30,31,45-47), (48)-->(49,50), (31)==(47), (47)==(31), (8)==(45), (45)==(8)
│ │ ├── limit hint: 1.00
│ │ ├── inner-join (lookup commission_rate)
│ │ │ ├── columns: c_id:1!null c_tier:8!null cr_c_tier:45!null cr_tt_id:46!null cr_ex_id:47!null cr_from_qty:48!null cr_to_qty:49!null commission_rate.cr_rate:50!null
│ │ │ ├── key columns: [8 57] = [45 46]
│ │ │ ├── key: (47,48)
│ │ │ ├── fd: ()-->(1,8,45,46), (47,48)-->(49,50), (8)==(45), (45)==(8)
│ │ │ ├── project
│ │ │ │ ├── columns: "lookup_join_const_col_@46":57!null c_id:1!null c_tier:8!null
│ │ │ ├── columns: s_symb:27!null s_name:30!null s_ex_id:31!null cr_c_tier:45!null cr_tt_id:46!null cr_ex_id:47!null cr_from_qty:48!null cr_to_qty:49!null commission_rate.cr_rate:50!null
│ │ │ ├── lookup expression
│ │ │ │ └── filters
│ │ │ │ ├── cr_ex_id:47 = s_ex_id:31 [outer=(31,47), constraints=(/31: (/NULL - ]; /47: (/NULL - ]), fd=(31)==(47), (47)==(31)]
│ │ │ │ ├── cr_c_tier:45 IN (1, 2, 3) [outer=(45), constraints=(/45: [/1 - /1] [/2 - /2] [/3 - /3]; tight)]
│ │ │ │ ├── cr_tt_id:46 = 'TLS' [outer=(46), constraints=(/46: [/'TLS' - /'TLS']; tight), fd=()-->(46)]
│ │ │ │ └── cr_from_qty:48 <= 100 [outer=(48), constraints=(/48: (/NULL - /100]; tight)]
│ │ │ ├── key: (45,48)
│ │ │ ├── fd: ()-->(27,30,31,46,47), (45,48)-->(49,50), (31)==(47), (47)==(31)
│ │ │ ├── scan security
│ │ │ │ ├── columns: s_symb:27!null s_name:30!null s_ex_id:31!null
│ │ │ │ ├── constraint: /27: [/'ROACH' - /'ROACH']
│ │ │ │ ├── cardinality: [0 - 1]
│ │ │ │ ├── key: ()
│ │ │ │ ├── fd: ()-->(1,8,57)
│ │ │ │ ├── scan customer
│ │ │ │ │ ├── columns: c_id:1!null c_tier:8!null
│ │ │ │ │ ├── constraint: /1: [/0 - /0]
│ │ │ │ │ ├── cardinality: [0 - 1]
│ │ │ │ │ ├── key: ()
│ │ │ │ │ └── fd: ()-->(1,8)
│ │ │ │ └── projections
│ │ │ │ └── 'TLS' [as="lookup_join_const_col_@46":57]
│ │ │ │ └── fd: ()-->(27,30,31)
│ │ │ └── filters
│ │ │ ├── cr_from_qty:48 <= 100 [outer=(48), constraints=(/48: (/NULL - /100]; tight)]
│ │ │ └── cr_to_qty:49 >= 200 [outer=(49), constraints=(/49: [/200 - ]; tight)]
│ │ ├── scan security
│ │ │ ├── columns: s_symb:27!null s_name:30!null s_ex_id:31!null
│ │ │ ├── constraint: /27: [/'ROACH' - /'ROACH']
│ │ ├── scan customer
│ │ │ ├── columns: c_id:1!null c_tier:8!null
│ │ │ ├── constraint: /1: [/0 - /0]
│ │ │ ├── cardinality: [0 - 1]
│ │ │ ├── key: ()
│ │ │ └── fd: ()-->(27,30,31)
│ │ │ └── fd: ()-->(1,8)
│ │ └── filters
│ │ └── cr_ex_id:47 = s_ex_id:31 [outer=(31,47), constraints=(/31: (/NULL - ]; /47: (/NULL - ]), fd=(31)==(47), (47)==(31)]
│ │ └── cr_c_tier:45 = c_tier:8 [outer=(8,45), constraints=(/8: (/NULL - ]; /45: (/NULL - ]), fd=(8)==(45), (45)==(8)]
│ └── 1
└── projections
└── commission_rate.cr_rate:50::FLOAT8 [as=cr_rate:53, outer=(50), immutable]
Expand Down Expand Up @@ -4097,34 +4094,26 @@ project
│ │ ├── key: (48)
│ │ ├── fd: ()-->(1,8,27,30,31,45-47), (48)-->(49,50), (8)==(45), (45)==(8), (31)==(47), (47)==(31)
│ │ ├── limit hint: 1.00
│ │ ├── project
│ │ │ ├── columns: "lookup_join_const_col_@46":54!null c_id:1!null c_tier:8!null s_symb:27!null s_name:30!null s_ex_id:31!null
│ │ ├── inner-join (cross)
│ │ │ ├── columns: c_id:1!null c_tier:8!null s_symb:27!null s_name:30!null s_ex_id:31!null
│ │ │ ├── cardinality: [0 - 1]
│ │ │ ├── multiplicity: left-rows(zero-or-one), right-rows(zero-or-one)
│ │ │ ├── key: ()
│ │ │ ├── fd: ()-->(1,8,27,30,31,54)
│ │ │ ├── fd: ()-->(1,8,27,30,31)
│ │ │ ├── limit hint: 1.00
│ │ │ ├── inner-join (cross)
│ │ │ │ ├── columns: c_id:1!null c_tier:8!null s_symb:27!null s_name:30!null s_ex_id:31!null
│ │ │ ├── scan customer
│ │ │ │ ├── columns: c_id:1!null c_tier:8!null
│ │ │ │ ├── constraint: /1: [/0 - /0]
│ │ │ │ ├── cardinality: [0 - 1]
│ │ │ │ ├── multiplicity: left-rows(zero-or-one), right-rows(zero-or-one)
│ │ │ │ ├── key: ()
│ │ │ │ ├── fd: ()-->(1,8,27,30,31)
│ │ │ │ ├── limit hint: 1.00
│ │ │ │ ├── scan customer
│ │ │ │ │ ├── columns: c_id:1!null c_tier:8!null
│ │ │ │ │ ├── constraint: /1: [/0 - /0]
│ │ │ │ │ ├── cardinality: [0 - 1]
│ │ │ │ │ ├── key: ()
│ │ │ │ │ └── fd: ()-->(1,8)
│ │ │ │ ├── scan security
│ │ │ │ │ ├── columns: s_symb:27!null s_name:30!null s_ex_id:31!null
│ │ │ │ │ ├── constraint: /27: [/'ROACH' - /'ROACH']
│ │ │ │ │ ├── cardinality: [0 - 1]
│ │ │ │ │ ├── key: ()
│ │ │ │ │ └── fd: ()-->(27,30,31)
│ │ │ │ └── filters (true)
│ │ │ └── projections
│ │ │ └── 'TLS' [as="lookup_join_const_col_@46":54]
│ │ │ │ └── fd: ()-->(1,8)
│ │ │ ├── scan security
│ │ │ │ ├── columns: s_symb:27!null s_name:30!null s_ex_id:31!null
│ │ │ │ ├── constraint: /27: [/'ROACH' - /'ROACH']
│ │ │ │ ├── cardinality: [0 - 1]
│ │ │ │ ├── key: ()
│ │ │ │ └── fd: ()-->(27,30,31)
│ │ │ └── filters (true)
│ │ └── filters
│ │ └── cr_to_qty:49 >= 200 [outer=(49), constraints=(/49: [/200 - ]; tight)]
│ └── 1
Expand Down
76 changes: 33 additions & 43 deletions pkg/sql/opt/xform/testdata/external/tpce-no-stats
Original file line number Diff line number Diff line change
Expand Up @@ -4060,34 +4060,31 @@ project
│ │ ├── fd: ()-->(1,8,27,30,31,45-47), (48)-->(49,50), (31)==(47), (47)==(31), (8)==(45), (45)==(8)
│ │ ├── limit hint: 1.00
│ │ ├── inner-join (lookup commission_rate)
│ │ │ ├── columns: c_id:1!null c_tier:8!null cr_c_tier:45!null cr_tt_id:46!null cr_ex_id:47!null cr_from_qty:48!null cr_to_qty:49!null commission_rate.cr_rate:50!null
│ │ │ ├── key columns: [8 57] = [45 46]
│ │ │ ├── key: (47,48)
│ │ │ ├── fd: ()-->(1,8,45,46), (47,48)-->(49,50), (8)==(45), (45)==(8)
│ │ │ ├── project
│ │ │ │ ├── columns: "lookup_join_const_col_@46":57!null c_id:1!null c_tier:8!null
│ │ │ ├── columns: s_symb:27!null s_name:30!null s_ex_id:31!null cr_c_tier:45!null cr_tt_id:46!null cr_ex_id:47!null cr_from_qty:48!null cr_to_qty:49!null commission_rate.cr_rate:50!null
│ │ │ ├── lookup expression
│ │ │ │ └── filters
│ │ │ │ ├── cr_ex_id:47 = s_ex_id:31 [outer=(31,47), constraints=(/31: (/NULL - ]; /47: (/NULL - ]), fd=(31)==(47), (47)==(31)]
│ │ │ │ ├── cr_c_tier:45 IN (1, 2, 3) [outer=(45), constraints=(/45: [/1 - /1] [/2 - /2] [/3 - /3]; tight)]
│ │ │ │ ├── cr_tt_id:46 = 'TLS' [outer=(46), constraints=(/46: [/'TLS' - /'TLS']; tight), fd=()-->(46)]
│ │ │ │ └── cr_from_qty:48 <= 100 [outer=(48), constraints=(/48: (/NULL - /100]; tight)]
│ │ │ ├── key: (45,48)
│ │ │ ├── fd: ()-->(27,30,31,46,47), (45,48)-->(49,50), (31)==(47), (47)==(31)
│ │ │ ├── scan security
│ │ │ │ ├── columns: s_symb:27!null s_name:30!null s_ex_id:31!null
│ │ │ │ ├── constraint: /27: [/'ROACH' - /'ROACH']
│ │ │ │ ├── cardinality: [0 - 1]
│ │ │ │ ├── key: ()
│ │ │ │ ├── fd: ()-->(1,8,57)
│ │ │ │ ├── scan customer
│ │ │ │ │ ├── columns: c_id:1!null c_tier:8!null
│ │ │ │ │ ├── constraint: /1: [/0 - /0]
│ │ │ │ │ ├── cardinality: [0 - 1]
│ │ │ │ │ ├── key: ()
│ │ │ │ │ └── fd: ()-->(1,8)
│ │ │ │ └── projections
│ │ │ │ └── 'TLS' [as="lookup_join_const_col_@46":57]
│ │ │ │ └── fd: ()-->(27,30,31)
│ │ │ └── filters
│ │ │ ├── cr_from_qty:48 <= 100 [outer=(48), constraints=(/48: (/NULL - /100]; tight)]
│ │ │ └── cr_to_qty:49 >= 200 [outer=(49), constraints=(/49: [/200 - ]; tight)]
│ │ ├── scan security
│ │ │ ├── columns: s_symb:27!null s_name:30!null s_ex_id:31!null
│ │ │ ├── constraint: /27: [/'ROACH' - /'ROACH']
│ │ ├── scan customer
│ │ │ ├── columns: c_id:1!null c_tier:8!null
│ │ │ ├── constraint: /1: [/0 - /0]
│ │ │ ├── cardinality: [0 - 1]
│ │ │ ├── key: ()
│ │ │ └── fd: ()-->(27,30,31)
│ │ │ └── fd: ()-->(1,8)
│ │ └── filters
│ │ └── cr_ex_id:47 = s_ex_id:31 [outer=(31,47), constraints=(/31: (/NULL - ]; /47: (/NULL - ]), fd=(31)==(47), (47)==(31)]
│ │ └── cr_c_tier:45 = c_tier:8 [outer=(8,45), constraints=(/8: (/NULL - ]; /45: (/NULL - ]), fd=(8)==(45), (45)==(8)]
│ └── 1
└── projections
└── commission_rate.cr_rate:50::FLOAT8 [as=cr_rate:53, outer=(50), immutable]
Expand Down Expand Up @@ -4128,32 +4125,25 @@ project
│ │ ├── key: (48)
│ │ ├── fd: ()-->(1,8,27,30,31,45-47), (48)-->(49,50), (8)==(45), (45)==(8), (31)==(47), (47)==(31)
│ │ ├── limit hint: 1.00
│ │ ├── project
│ │ │ ├── columns: "lookup_join_const_col_@46":54!null c_id:1!null c_tier:8!null s_symb:27!null s_name:30!null s_ex_id:31!null
│ │ ├── inner-join (cross)
│ │ │ ├── columns: c_id:1!null c_tier:8!null s_symb:27!null s_name:30!null s_ex_id:31!null
│ │ │ ├── cardinality: [0 - 1]
│ │ │ ├── multiplicity: left-rows(zero-or-one), right-rows(zero-or-one)
│ │ │ ├── key: ()
│ │ │ ├── fd: ()-->(1,8,27,30,31,54)
│ │ │ ├── inner-join (cross)
│ │ │ │ ├── columns: c_id:1!null c_tier:8!null s_symb:27!null s_name:30!null s_ex_id:31!null
│ │ │ ├── fd: ()-->(1,8,27,30,31)
│ │ │ ├── scan customer
│ │ │ │ ├── columns: c_id:1!null c_tier:8!null
│ │ │ │ ├── constraint: /1: [/0 - /0]
│ │ │ │ ├── cardinality: [0 - 1]
│ │ │ │ ├── multiplicity: left-rows(zero-or-one), right-rows(zero-or-one)
│ │ │ │ ├── key: ()
│ │ │ │ ├── fd: ()-->(1,8,27,30,31)
│ │ │ │ ├── scan customer
│ │ │ │ │ ├── columns: c_id:1!null c_tier:8!null
│ │ │ │ │ ├── constraint: /1: [/0 - /0]
│ │ │ │ │ ├── cardinality: [0 - 1]
│ │ │ │ │ ├── key: ()
│ │ │ │ │ └── fd: ()-->(1,8)
│ │ │ │ ├── scan security
│ │ │ │ │ ├── columns: s_symb:27!null s_name:30!null s_ex_id:31!null
│ │ │ │ │ ├── constraint: /27: [/'ROACH' - /'ROACH']
│ │ │ │ │ ├── cardinality: [0 - 1]
│ │ │ │ │ ├── key: ()
│ │ │ │ │ └── fd: ()-->(27,30,31)
│ │ │ │ └── filters (true)
│ │ │ └── projections
│ │ │ └── 'TLS' [as="lookup_join_const_col_@46":54]
│ │ │ │ └── fd: ()-->(1,8)
│ │ │ ├── scan security
│ │ │ │ ├── columns: s_symb:27!null s_name:30!null s_ex_id:31!null
│ │ │ │ ├── constraint: /27: [/'ROACH' - /'ROACH']
│ │ │ │ ├── cardinality: [0 - 1]
│ │ │ │ ├── key: ()
│ │ │ │ └── fd: ()-->(27,30,31)
│ │ │ └── filters (true)
│ │ └── filters
│ │ └── cr_to_qty:49 >= 200 [outer=(49), constraints=(/49: [/200 - ]; tight)]
│ └── 1
Expand Down
Loading

0 comments on commit 9b51fc1

Please sign in to comment.