Skip to content

Commit

Permalink
opt: improve composite check for join filter remapping
Browse files Browse the repository at this point in the history
Use CanBeCompositeSensitive to allow remapping insensitive join
filters.

Release note: None
  • Loading branch information
RaduBerinde committed Oct 2, 2020
1 parent 185474c commit 5bc1751
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 7 deletions.
15 changes: 9 additions & 6 deletions pkg/sql/opt/norm/join_funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ func (c *CustomFuncs) canMapJoinOpEquivalenceGroup(
leftCols, rightCols opt.ColSet,
equivFD props.FuncDepSet,
) bool {
eqCols := c.GetEquivColsWithEquivType(col, equivFD)
eqCols := c.GetEquivColsWithEquivType(col, equivFD, false /* allowCompositeEncoding */)

// To map equality conditions, the equivalent columns must intersect
// both sides and must be fully bound by both sides.
Expand Down Expand Up @@ -201,7 +201,7 @@ func (c *CustomFuncs) mapJoinOpEquivalenceGroup(
leftCols, rightCols opt.ColSet,
equivFD props.FuncDepSet,
) memo.FiltersExpr {
eqCols := c.GetEquivColsWithEquivType(col, equivFD)
eqCols := c.GetEquivColsWithEquivType(col, equivFD, false /* allowCompositeEncoding */)

// First remove all the equality conditions for this equivalence group.
newFilters := make(memo.FiltersExpr, 0, len(filters))
Expand Down Expand Up @@ -289,10 +289,12 @@ func (c *CustomFuncs) CanMapJoinOpFilter(
return false
}

allowCompositeEncoding := !memo.CanBeCompositeSensitive(c.mem.Metadata(), src)

// For CanMapJoinOpFilter to be true, each column in src must map to at
// least one column in dst.
for i, ok := scalarProps.OuterCols.Next(0); ok; i, ok = scalarProps.OuterCols.Next(i + 1) {
eqCols := c.GetEquivColsWithEquivType(i, equivFD)
eqCols := c.GetEquivColsWithEquivType(i, equivFD, allowCompositeEncoding)
if !eqCols.Intersects(dstCols) {
return false
}
Expand Down Expand Up @@ -331,12 +333,13 @@ func (c *CustomFuncs) MapJoinOpFilter(
return src.Condition
}

allowCompositeEncoding := !memo.CanBeCompositeSensitive(c.mem.Metadata(), src)
// Map each column in src to one column in dst. We choose an arbitrary column
// (the one with the smallest ColumnID) if there are multiple choices.
var colMap util.FastIntMap
outerCols := src.ScalarProps().OuterCols
for srcCol, ok := outerCols.Next(0); ok; srcCol, ok = outerCols.Next(srcCol + 1) {
eqCols := c.GetEquivColsWithEquivType(srcCol, equivFD)
eqCols := c.GetEquivColsWithEquivType(srcCol, equivFD, allowCompositeEncoding)
eqCols.IntersectionWith(dstCols)
if eqCols.Contains(srcCol) {
colMap.Set(int(srcCol), int(srcCol))
Expand Down Expand Up @@ -404,14 +407,14 @@ func (c *CustomFuncs) MapJoinOpFilter(
// TODO(rytaft): In the future, we may want to allow the mapping if the
// filter involves a comparison operator, such as x < 5.
func (c *CustomFuncs) GetEquivColsWithEquivType(
col opt.ColumnID, equivFD props.FuncDepSet,
col opt.ColumnID, equivFD props.FuncDepSet, allowCompositeEncoding bool,
) opt.ColSet {
var res opt.ColSet
colType := c.f.Metadata().ColumnMeta(col).Type

// Don't bother looking for equivalent columns if colType has a composite
// key encoding.
if colinfo.HasCompositeKeyEncoding(colType) {
if !allowCompositeEncoding && colinfo.HasCompositeKeyEncoding(colType) {
res.Add(col)
return res
}
Expand Down
37 changes: 36 additions & 1 deletion pkg/sql/opt/norm/testdata/rules/join
Original file line number Diff line number Diff line change
Expand Up @@ -729,7 +729,7 @@ project
# Ensure that we do not map filters for types with composite key encoding.
norm expect-not=(PushFilterIntoJoinLeftAndRight,MapFilterIntoJoinLeft,MapFilterIntoJoinRight)
SELECT *
FROM (VALUES (1.0), (2.0)) AS t1(x), (VALUES (1.00), (2.00)) AS t2(y)WHERE x=y AND x::text = '1.0'
FROM (VALUES (1.0), (2.0)) AS t1(x), (VALUES (1.00), (2.00)) AS t2(y) WHERE x=y AND x::text = '1.0'
----
inner-join (hash)
├── columns: x:1!null y:2!null
Expand All @@ -755,6 +755,41 @@ inner-join (hash)
└── filters
└── column1:1 = column1:2 [outer=(1,2), immutable, constraints=(/1: (/NULL - ]; /2: (/NULL - ]), fd=(1)==(2), (2)==(1)]

# Remap composite variables if filters are not composite sensitive.
norm expect=PushFilterIntoJoinLeftAndRight
SELECT *
FROM (VALUES (1.0), (2.0)) AS t1(x), (VALUES (1.00), (2.00)) AS t2(y) WHERE x=y AND x >= 1
----
inner-join (hash)
├── columns: x:1!null y:2!null
├── cardinality: [0 - 4]
├── immutable
├── fd: (1)==(2), (2)==(1)
├── select
│ ├── columns: column1:1!null
│ ├── cardinality: [0 - 2]
│ ├── immutable
│ ├── values
│ │ ├── columns: column1:1!null
│ │ ├── cardinality: [2 - 2]
│ │ ├── (1.0,)
│ │ └── (2.0,)
│ └── filters
│ └── column1:1 >= 1 [outer=(1), immutable, constraints=(/1: [/1 - ]; tight)]
├── select
│ ├── columns: column1:2!null
│ ├── cardinality: [0 - 2]
│ ├── immutable
│ ├── values
│ │ ├── columns: column1:2!null
│ │ ├── cardinality: [2 - 2]
│ │ ├── (1.00,)
│ │ └── (2.00,)
│ └── filters
│ └── column1:2 >= 1 [outer=(2), immutable, constraints=(/2: [/1 - ]; tight)]
└── filters
└── column1:1 = column1:2 [outer=(1,2), immutable, constraints=(/1: (/NULL - ]; /2: (/NULL - ]), fd=(1)==(2), (2)==(1)]

# Optimization does not apply if equality is only on one side.
norm expect-not=(PushFilterIntoJoinLeftAndRight,MapFilterIntoJoinLeft,MapFilterIntoJoinRight)
SELECT * FROM a INNER JOIN b ON b.y=b.x AND a.k=a.i AND a.k + b.y > 5 AND b.x * a.i = 3
Expand Down

0 comments on commit 5bc1751

Please sign in to comment.