Commit 14318ede authored by Drew Kimball's avatar Drew Kimball

opt: modify PushAggDistinctIntoScalarGroupBy to handle GroupBy

This patch modifies the PushAggDistinctIntoScalarGroupBy rule to
match GroupBy operators.

Release note: None
parent 3a03f384
......@@ -842,16 +842,17 @@ EXPLAIN (VEC) SELECT p_brand, p_type, p_size, count(distinct ps_suppkey) AS supp
└ Node 1
└ *colexec.sortOp
└ *rowexec.hashAggregator
└ *colexec.hashJoiner
├ *colexec.mergeJoinLeftAntiOp
│ ├ *colfetcher.colBatchScan
│ └ *colexec.selRegexpBytesBytesConstOp
│ └ *colfetcher.colBatchScan
└ *colexec.selectInOpInt64
└ *colexec.selNotPrefixBytesBytesConstOp
└ *colexec.selNEBytesBytesConstOp
└ *colfetcher.colBatchScan
└ *colexec.hashAggregator
└ *colexec.unorderedDistinct
└ *colexec.hashJoiner
├ *colexec.mergeJoinLeftAntiOp
│ ├ *colfetcher.colBatchScan
│ └ *colexec.selRegexpBytesBytesConstOp
│ └ *colfetcher.colBatchScan
└ *colexec.selectInOpInt64
└ *colexec.selNotPrefixBytesBytesConstOp
└ *colexec.selNEBytesBytesConstOp
└ *colfetcher.colBatchScan
# Query 17
query T
......
......@@ -398,22 +398,6 @@ func (c *CustomFuncs) NonKeyCols(in memo.RelExpr) opt.ColSet {
return c.OutputCols(in).Difference(keyCols)
}
// MakeAggCols constructs a new Aggregations operator containing an aggregate
// function of the given operator type for each of column in the given set. For
// example, for ConstAggOp and columns (1,2), this expression is returned:
//
// (Aggregations
// [(ConstAgg (Variable 1)) (ConstAgg (Variable 2))]
// [1,2]
// )
//
func (c *CustomFuncs) MakeAggCols(aggOp opt.Operator, cols opt.ColSet) memo.AggregationsExpr {
colsLen := cols.Len()
aggs := make(memo.AggregationsExpr, colsLen)
c.makeAggCols(aggOp, cols, aggs)
return aggs
}
// MakeAggCols2 is similar to MakeAggCols, except that it allows two different
// sets of aggregate functions to be added to the resulting Aggregations
// operator, with one set appended to the other, like this:
......@@ -433,6 +417,29 @@ func (c *CustomFuncs) MakeAggCols2(
return aggs
}
// AppendAggCols2 constructs a new Aggregations operator containing the
// aggregate functions from an existing Aggregations operator plus an
// additional set of aggregate functions, one for each column in the given set.
// The new functions are of the given aggregate operator type.
func (c *CustomFuncs) AppendAggCols2(
aggs memo.AggregationsExpr,
aggOp opt.Operator,
cols opt.ColSet,
aggOp2 opt.Operator,
cols2 opt.ColSet,
) memo.AggregationsExpr {
colsLen := cols.Len()
outAggs := make(memo.AggregationsExpr, len(aggs)+colsLen+cols2.Len())
copy(outAggs, aggs)
offset := len(aggs)
c.makeAggCols(aggOp, cols, outAggs[offset:])
offset += colsLen
c.makeAggCols(aggOp2, cols2, outAggs[offset:])
return outAggs
}
// EnsureCanaryCol checks whether an aggregation which cannot ignore nulls exists.
// If one does, it then checks if there are any non-null columns in the input.
// If there is not one, it synthesizes a new True constant column that is
......
......@@ -840,6 +840,35 @@ func (c *CustomFuncs) ExtractGroupingOrdering(
return private.Ordering
}
// AppendAggCols constructs a new Aggregations operator containing the aggregate
// functions from an existing Aggregations operator plus an additional set of
// aggregate functions, one for each column in the given set. The new functions
// are of the given aggregate operator type.
func (c *CustomFuncs) AppendAggCols(
aggs memo.AggregationsExpr, aggOp opt.Operator, cols opt.ColSet,
) memo.AggregationsExpr {
outAggs := make(memo.AggregationsExpr, len(aggs)+cols.Len())
copy(outAggs, aggs)
c.makeAggCols(aggOp, cols, outAggs[len(aggs):])
return outAggs
}
// MakeAggCols constructs a new Aggregations operator containing an aggregate
// function of the given operator type for each of column in the given set. For
// example, for ConstAggOp and columns (1,2), this expression is returned:
//
// (Aggregations
// [(ConstAgg (Variable 1)) (ConstAgg (Variable 2))]
// [1,2]
// )
//
func (c *CustomFuncs) MakeAggCols(aggOp opt.Operator, cols opt.ColSet) memo.AggregationsExpr {
colsLen := cols.Len()
aggs := make(memo.AggregationsExpr, colsLen)
c.makeAggCols(aggOp, cols, aggs)
return aggs
}
// ----------------------------------------------------------------------
//
// Join functions
......
......@@ -31,42 +31,6 @@ func (c *CustomFuncs) RemoveGroupingCols(
return &p
}
// AppendAggCols constructs a new Aggregations operator containing the aggregate
// functions from an existing Aggregations operator plus an additional set of
// aggregate functions, one for each column in the given set. The new functions
// are of the given aggregate operator type.
func (c *CustomFuncs) AppendAggCols(
aggs memo.AggregationsExpr, aggOp opt.Operator, cols opt.ColSet,
) memo.AggregationsExpr {
outAggs := make(memo.AggregationsExpr, len(aggs)+cols.Len())
copy(outAggs, aggs)
c.makeAggCols(aggOp, cols, outAggs[len(aggs):])
return outAggs
}
// AppendAggCols2 constructs a new Aggregations operator containing the
// aggregate functions from an existing Aggregations operator plus an
// additional set of aggregate functions, one for each column in the given set.
// The new functions are of the given aggregate operator type.
func (c *CustomFuncs) AppendAggCols2(
aggs memo.AggregationsExpr,
aggOp opt.Operator,
cols opt.ColSet,
aggOp2 opt.Operator,
cols2 opt.ColSet,
) memo.AggregationsExpr {
colsLen := cols.Len()
outAggs := make(memo.AggregationsExpr, len(aggs)+colsLen+cols2.Len())
copy(outAggs, aggs)
offset := len(aggs)
c.makeAggCols(aggOp, cols, outAggs[offset:])
offset += colsLen
c.makeAggCols(aggOp2, cols2, outAggs[offset:])
return outAggs
}
// makeAggCols is a helper method that constructs a new aggregate function of
// the given operator type for each column in the given set. The resulting
// aggregates are written into outElems and outColList. As an example, for
......
......@@ -322,13 +322,13 @@
$aggregations
)
# PushAggDistinctIntoScalarGroupBy pushes an aggregate function DISTINCT
# modifier into the input of the ScalarGroupBy operator. This allows the
# optimizer to take advantage of an index on the column(s) subject to the
# DISTINCT operation. PushAggDistinctIntoScalarGroupBy can match any single
# aggregate function, including those that have multiple input arguments.
[PushAggDistinctIntoScalarGroupBy, Normalize]
(ScalarGroupBy
# PushAggDistinctIntoGroupBy pushes an aggregate function DISTINCT modifier into
# the input of a GroupBy or ScalarGroupBy operator. This allows the optimizer to
# take advantage of an index on the column(s) subject to the DISTINCT operation.
# PushAggDistinctIntoGroupBy can match any single aggregate function, including
# those that have multiple input arguments.
[PushAggDistinctIntoGroupBy, Normalize]
(GroupBy | ScalarGroupBy
$input:*
$aggregations:[
$item:(AggregationsItem (AggDistinct $agg:*) $aggColID:*)
......@@ -336,12 +336,20 @@
$groupingPrivate:*
)
=>
(ScalarGroupBy
((OpName)
(DistinctOn
$input
[]
(MakeAggCols
FirstAgg
(OrderingCols
(ExtractGroupingOrdering $groupingPrivate)
)
)
(MakeGrouping
(ExtractAggInputColumns $agg)
(UnionCols
(GroupingCols $groupingPrivate)
(ExtractAggInputColumns $agg)
)
(EmptyOrdering)
)
)
......
......@@ -1380,7 +1380,8 @@ project
└── sum [as=sum:6, outer=(1)]
└── k:1
# GroupBy with no key.
# GroupBy with no key. The AggDistinct is instead pushed into the GroupBy by
# PushAggDistinctIntoGroupBy.
norm expect-not=EliminateAggDistinctForKeys
SELECT sum(DISTINCT a) FROM abc GROUP BY b
----
......@@ -1391,12 +1392,15 @@ project
├── grouping columns: b:2!null
├── key: (2)
├── fd: (2)-->(4)
├── scan abc
│ └── columns: a:1!null b:2!null
├── distinct-on
│ ├── columns: a:1!null b:2!null
│ ├── grouping columns: a:1!null b:2!null
│ ├── key: (1,2)
│ └── scan abc
│ └── columns: a:1!null b:2!null
└── aggregations
└── agg-distinct [as=sum:4, outer=(1)]
└── sum
└── a:1
└── sum [as=sum:4, outer=(1)]
└── a:1
# GroupBy with composite key formed by argument plus grouping columns.
norm expect=EliminateAggDistinctForKeys
......@@ -2704,11 +2708,11 @@ insert a
└── "?column?":11
# --------------------------------------------------
# PushAggDistinctIntoScalarGroupBy
# PushAggDistinctIntoGroupBy
# --------------------------------------------------
# SUM case.
norm expect=PushAggDistinctIntoScalarGroupBy
norm expect=PushAggDistinctIntoGroupBy
SELECT sum(DISTINCT y) FROM xyzbs
----
scalar-group-by
......@@ -2727,7 +2731,7 @@ scalar-group-by
└── y:2
# COUNT case. Expecting an index scan because opt command is used.
opt expect=PushAggDistinctIntoScalarGroupBy
opt expect=PushAggDistinctIntoGroupBy
SELECT count(DISTINCT y) FROM xyzbs
----
scalar-group-by
......@@ -2748,7 +2752,7 @@ scalar-group-by
└── y:2
# AVG case.
norm expect=PushAggDistinctIntoScalarGroupBy
norm expect=PushAggDistinctIntoGroupBy
SELECT avg(DISTINCT y) FROM xyzbs
----
scalar-group-by
......@@ -2767,7 +2771,7 @@ scalar-group-by
└── y:2
# JSON_AGG case.
norm expect=PushAggDistinctIntoScalarGroupBy
norm expect=PushAggDistinctIntoGroupBy
SELECT json_agg(DISTINCT y) FROM xyzbs
----
scalar-group-by
......@@ -2787,7 +2791,7 @@ scalar-group-by
# CORR case.
# Multiple input arguments for aggregate function.
norm expect=PushAggDistinctIntoScalarGroupBy
norm expect=PushAggDistinctIntoGroupBy
SELECT corr(DISTINCT y, z) FROM xyzbs
----
scalar-group-by
......@@ -2808,7 +2812,7 @@ scalar-group-by
# STRING_AGG case.
# Multiple input arguments for aggregate function.
norm expect=PushAggDistinctIntoScalarGroupBy
norm expect=PushAggDistinctIntoGroupBy
SELECT string_agg(DISTINCT s, '-') FROM xyzbs
----
scalar-group-by
......@@ -2838,7 +2842,7 @@ scalar-group-by
# STRING_AGG case with an ORDER BY.
# Multiple input arguments for aggregate function.
norm expect=PushAggDistinctIntoScalarGroupBy
norm expect=PushAggDistinctIntoGroupBy
SELECT string_agg(DISTINCT s, '-') FROM (SELECT s FROM xyzbs ORDER BY s)
----
scalar-group-by
......@@ -2865,6 +2869,8 @@ scalar-group-by
│ │ └── projections
│ │ └── '-' [as=column6:6]
│ └── aggregations
│ ├── first-agg [as=s:5, outer=(5)]
│ │ └── s:5
│ └── const-agg [as=column6:6, outer=(6)]
│ └── column6:6
└── aggregations
......@@ -2872,9 +2878,102 @@ scalar-group-by
├── s:5
└── column6:6
# Case with a GroupBy operator.
norm expect=PushAggDistinctIntoGroupBy
SELECT b, count(DISTINCT y) FROM xyzbs GROUP BY b
----
group-by
├── columns: b:4!null count:6!null
├── grouping columns: b:4!null
├── key: (4)
├── fd: (4)-->(6)
├── distinct-on
│ ├── columns: y:2 b:4!null
│ ├── grouping columns: y:2 b:4!null
│ ├── key: (2,4)
│ └── scan xyzbs
│ └── columns: y:2 b:4!null
└── aggregations
└── count [as=count:6, outer=(2)]
└── y:2
# Case with a GroupBy operator grouping on multiple columns.
norm expect=PushAggDistinctIntoGroupBy
SELECT b, s, count(DISTINCT y) FROM xyzbs GROUP BY b, s
----
group-by
├── columns: b:4!null s:5 count:6!null
├── grouping columns: b:4!null s:5
├── key: (4,5)
├── fd: (4,5)-->(6)
├── distinct-on
│ ├── columns: y:2 b:4!null s:5
│ ├── grouping columns: y:2 b:4!null s:5
│ ├── key: (2,4,5)
│ └── scan xyzbs
│ └── columns: y:2 b:4!null s:5
└── aggregations
└── count [as=count:6, outer=(2)]
└── y:2
# Case with a GroupBy operator and an aggregate with multiple input columns.
norm expect=PushAggDistinctIntoGroupBy
SELECT s, corr(DISTINCT y, z) FROM xyzbs GROUP BY s
----
group-by
├── columns: s:5 corr:6
├── grouping columns: s:5
├── key: (5)
├── fd: (5)-->(6)
├── distinct-on
│ ├── columns: y:2 z:3!null s:5
│ ├── grouping columns: y:2 z:3!null s:5
│ ├── key: (2,3,5)
│ └── scan xyzbs
│ └── columns: y:2 z:3!null s:5
└── aggregations
└── corr [as=corr:6, outer=(2,3)]
├── y:2
└── z:3
# The ordering columns of the GroupBy operator should become FirstAggs in the
# DistinctOn. This ensures that the ordering columns are available for the
# GroupBy operator.
norm expect=PushAggDistinctIntoGroupBy
SELECT array_agg(DISTINCT s) FROM (SELECT * FROM a ORDER BY i) GROUP BY f
----
project
├── columns: array_agg:6!null
└── group-by
├── columns: f:3 array_agg:6!null
├── grouping columns: f:3
├── internal-ordering: +2 opt(3)
├── key: (3)
├── fd: (3)-->(6)
├── sort
│ ├── columns: i:2!null f:3 s:4!null
│ ├── key: (2,4)
│ ├── fd: (2,4)-->(3), (2,3)~~>(4), (3,4)-->(2)
│ ├── ordering: +2 opt(3) [actual: +2]
│ └── distinct-on
│ ├── columns: i:2!null f:3 s:4!null
│ ├── grouping columns: f:3 s:4!null
│ ├── key: (2,4)
│ ├── fd: (2,4)-->(3), (2,3)~~>(4), (3,4)-->(2)
│ ├── scan a
│ │ ├── columns: i:2!null f:3 s:4!null
│ │ ├── key: (2,4)
│ │ └── fd: (2,4)-->(3), (2,3)~~>(4)
│ └── aggregations
│ └── first-agg [as=i:2, outer=(2)]
│ └── i:2
└── aggregations
└── array-agg [as=array_agg:6, outer=(4)]
└── s:4
# No-op case where the same aggregate function is called on different
# columns.
norm expect-not=PushAggDistinctIntoScalarGroupBy
norm expect-not=PushAggDistinctIntoGroupBy
SELECT count(DISTINCT y), count(DISTINCT z) FROM xyzbs
----
scalar-group-by
......@@ -2894,7 +2993,7 @@ scalar-group-by
# No-op case where different aggregate functions are called on the same
# column.
norm expect-not=PushAggDistinctIntoScalarGroupBy
norm expect-not=PushAggDistinctIntoGroupBy
SELECT count(DISTINCT y), sum(DISTINCT y) FROM xyzbs
----
scalar-group-by
......@@ -2913,9 +3012,9 @@ scalar-group-by
└── y:2
# No-op cases where EliminateAggDistinct removes the AggDistinct before
# PushAggDistinctIntoScalarGroupBy is applied. Applies to MAX, MIN, BOOL_AND,
# PushAggDistinctIntoGroupBy is applied. Applies to MAX, MIN, BOOL_AND,
# and BOOL_OR.
norm expect-not=PushAggDistinctIntoScalarGroupBy
norm expect-not=PushAggDistinctIntoGroupBy
SELECT max(DISTINCT y) FROM xyzbs
----
scalar-group-by
......@@ -2929,7 +3028,7 @@ scalar-group-by
└── max [as=max:6, outer=(2)]
└── y:2
norm expect-not=PushAggDistinctIntoScalarGroupBy
norm expect-not=PushAggDistinctIntoGroupBy
SELECT bool_and(DISTINCT b) FROM xyzbs
----
scalar-group-by
......@@ -3333,7 +3432,7 @@ scalar-group-by
# No-op case because the DISTINCT requires the count input column, so the count
# can't be eliminated.
norm
norm expect-not=ConvertCountToCountRows
SELECT count(DISTINCT y) FROM xyzbs GROUP BY z
----
project
......@@ -3343,12 +3442,15 @@ project
├── grouping columns: z:3!null
├── key: (3)
├── fd: (3)-->(6)
├── scan xyzbs
│ └── columns: y:2 z:3!null
├── distinct-on
│ ├── columns: y:2 z:3!null
│ ├── grouping columns: y:2 z:3!null
│ ├── key: (2,3)
│ └── scan xyzbs
│ └── columns: y:2 z:3!null
└── aggregations
└── agg-distinct [as=count:6, outer=(2)]
└── count
└── y:2
└── count [as=count:6, outer=(2)]
└── y:2
# --------------------------------------------------
# FoldGroupingOperators
......
......@@ -247,7 +247,7 @@ project
# Aggregate function with DISTINCT.
norm expect=RejectNullsGroupBy
SELECT sum(DISTINCT y)
SELECT sum(DISTINCT y), max(y)
FROM (SELECT k FROM a)
LEFT JOIN (SELECT y FROM xy)
ON True
......@@ -255,19 +255,19 @@ GROUP BY k
HAVING sum(DISTINCT y)=1
----
project
├── columns: sum:7!null
├── columns: sum:7!null max:8!null
├── immutable
├── fd: ()-->(7)
└── select
├── columns: k:1!null sum:7!null
├── columns: k:1!null sum:7!null max:8!null
├── immutable
├── key: (1)
├── fd: ()-->(7)
├── fd: ()-->(7), (1)-->(8)
├── group-by
│ ├── columns: k:1!null sum:7!null
│ ├── columns: k:1!null sum:7!null max:8!null
│ ├── grouping columns: k:1!null
│ ├── key: (1)
│ ├── fd: (1)-->(7)
│ ├── fd: (1)-->(7,8)
│ ├── inner-join (cross)
│ │ ├── columns: k:1!null y:6!null
│ │ ├── scan a
......@@ -281,9 +281,11 @@ project
│ │ │ └── y:6 IS NOT NULL [outer=(6), constraints=(/6: (/NULL - ]; tight)]
│ │ └── filters (true)
│ └── aggregations
│ └── agg-distinct [as=sum:7, outer=(6)]
│ └── sum
│ └── y:6
│ ├── agg-distinct [as=sum:7, outer=(6)]
│ │ └── sum
│ │ └── y:6
│ └── max [as=max:8, outer=(6)]
│ └── y:6
└── filters
└── sum:7 = 1 [outer=(7), immutable, constraints=(/7: [/1 - /1]; tight), fd=()-->(7)]
......
......@@ -1765,51 +1765,53 @@ sort
├── grouping columns: p_brand:9!null p_type:10!null p_size:11!null
├── key: (9-11)
├── fd: (9-11)-->(22)
├── inner-join (hash)
│ ├── columns: ps_partkey:1!null ps_suppkey:2!null p_partkey:6!null p_brand:9!null p_type:10!null p_size:11!null
│ ├── multiplicity: left-rows(zero-or-one), right-rows(zero-or-more)
│ ├── key: (2,6)
│ ├── fd: (6)-->(9-11), (1)==(6), (6)==(1)
│ ├── anti-join (merge)
│ │ ├── columns: ps_partkey:1!null ps_suppkey:2!null
│ │ ├── left ordering: +2
│ │ ├── right ordering: +15
│ │ ├── key: (1,2)
│ │ ├── scan [email protected]_sk
│ │ │ ├── columns: ps_partkey:1!null ps_suppkey:2!null
│ │ │ ├── key: (1,2)
│ │ │ └── ordering: +2
│ │ ├── select
│ │ │ ├── columns: s_suppkey:15!null s_comment:21!null
│ │ │ ├── key: (15)
│ │ │ ├── fd: (15)-->(21)
│ │ │ ├── ordering: +15
│ │ │ ├── scan supplier
│ │ │ │ ├── columns: s_suppkey:15!null s_comment:21!null
│ │ │ │ ├── key: (15)
│ │ │ │ ├── fd: (15)-->(21)
│ │ │ │ └── ordering: +15
│ │ │ └── filters
│ │ │ └── s_comment:21 LIKE '%Customer%Complaints%' [outer=(21), constraints=(/21: (/NULL - ])]
│ │ └── filters (true)
│ ├── select
│ │ ├── columns: p_partkey:6!null p_brand:9!null p_type:10!null p_size:11!null
│ │ ├── key: (6)
│ │ ├── fd: (6)-->(9-11)
│ │ ├── scan part
│ │ │ ├── columns: p_partkey:6!null p_brand:9!null p_type:10!null p_size:11!null
│ │ │ ├── key: (6)
│ │ │ └── fd: (6)-->(9-11)
│ │ └── filters
│ │ ├── p_brand:9 != 'Brand#45' [outer=(9), constraints=(/9: (/NULL - /'Brand#45') [/e'Brand#45\x00' - ]; tight)]
│ │ ├── p_type:10 NOT LIKE 'MEDIUM POLISHED %' [outer=(10), constraints=(/10: (/NULL - ])]
│ │ └── p_size:11 IN (3, 9, 14, 19, 23, 36, 45, 49) [outer=(11), constraints=(/11: [/3 - /3] [/9 - /9] [/14 - /14] [/19 - /19] [/23 - /23] [/36 - /36] [/45 - /45] [/49 - /49]; tight)]
│ └── filters
│ └── p_partkey:6 = ps_partkey:1 [outer=(1,6), constraints=(/1: (/NULL - ]; /6: (/NULL - ]), fd=(1)==(6), (6)==(1)]
├── distinct-on
│ ├── columns: ps_suppkey:2!null p_brand:9!null p_type:10!null p_size:11!null
│ ├── grouping columns: ps_suppkey:2!null p_brand:9!null p_type:10!null p_size:11!null
│ ├── key: (2,9-11)
│ └── inner-join (hash)
│ ├── columns: ps_partkey:1!null ps_suppkey:2!null p_partkey:6!null p_brand:9!null p_type:10!null p_size:11!null
│ ├── multiplicity: left-rows(zero-or-one), right-rows(zero-or-more)
│ ├── key: (2,6)
│ ├── fd: (6)-->(9-11), (1)==(6), (6)==(1)
│ ├── anti-join (merge)
│ │ ├── columns: ps_partkey:1!null ps_suppkey:2!null
│ │ ├── left ordering: +2
│ │ ├── right ordering: +15
│ │ ├── key: (1,2)
│ │ ├── scan [email protected]_sk
│ │ │ ├── columns: ps_partkey:1!null ps_suppkey:2!null
│ │ │ ├── key: (1,2)
│ │ │ └── ordering: +2
│ │ ├── select
│ │ │ ├── columns: s_suppkey:15!null s_comment:21!null
│ │ │ ├── key: (15)
│ │ │ ├── fd: (15)-->(21)
│ │ │ ├── ordering: +15
│ │ │ ├── scan supplier
│ │ │ │ ├── columns: s_suppkey:15!null s_comment:21!null
│ │ │ │ ├── key: (15)
│ │ │ │ ├── fd: (15)-->(21)
│ │ │ │ └── ordering: +15
│ │ │ └── filters
│ │ │ └── s_comment:21 LIKE '%Customer%Complaints%' [outer=(21), constraints=(/21: (/NULL - ])]
│ │ └── filters (true)
│ ├── select
│ │ ├── columns: p_partkey:6!null p_brand:9!null p_type:10!null p_size:11!null
│ │ ├── key: (6)
│ │ ├── fd: (6)-->(9-11)
│ │ ├── scan part
│ │ │ ├── columns: p_partkey:6!null p_brand:9!null p_type:10!null p_size:11!null
│ │ │ ├── key: (6)
│ │ │ └── fd: (6)-->(9-11)
│ │ └── filters
│ │ ├── p_brand:9 != 'Brand#45' [outer=(9), constraints=(/9: (/NULL - /'Brand#45') [/e'Brand#45\x00' - ]; tight)]
│ │ ├── p_type:10 NOT LIKE 'MEDIUM POLISHED %' [outer=(10), constraints=(/10: (/NULL - ])]
│ │ └── p_size:11 IN (3, 9, 14, 19, 23, 36, 45, 49) [outer=(11), constraints=(/11: [/3 - /3] [/9 - /9] [/14 - /14] [/19 - /19] [/23 - /23] [/36 - /36] [/45 - /45] [/49 - /49]; tight)]
│ └── filters
│ └── p_partkey:6 = ps_partkey:1 [outer=(1,6), constraints=(/1: (/NULL - ]; /6: (/NULL - ]), fd=(1)==(6), (6)==(1)]
└── aggregations
└── agg-distinct [as=count:22, outer=(2)]
└── count
└── ps_suppkey:2
└── count-rows [as=count:22]
# --------------------------------------------------
# Q17
......
......@@ -1750,42 +1750,44 @@ sort
├── grouping columns: p_brand:9!null p_type:10!null p_size:11!null
├── key: (9-11)
├── fd: (9-11)-->(22)
├── inner-join (lookup part)
│ ├── columns: ps_partkey:1!null ps_suppkey:2!null p_partkey:6!null p_brand:9!null p_type:10!null p_size:11!null
│ ├── key columns: [1] = [6]
│ ├── lookup columns are key
│ ├── key: (2,6)
│ ├── fd: (6)-->(9-11), (1)==(6), (6)==(1)
│ ├── anti-join (merge)
│ │ ├── columns: ps_partkey:1!null ps_suppkey:2!null
│ │ ├── left ordering: +2
│ │ ├── right ordering: +15
│ │ ├── key: (1,2)
│ │ ├── scan [email protected]_sk
│ │ │ ├── columns: ps_partkey:1!null ps_suppkey:2!null
│ │ │ ├── key: (1,2)
│ │ │ └── ordering: +2
│ │ ├── select
│ │ │ ├── columns: s_suppkey:15!null s_comment:21!null
│ │ │ ├── key: (15)
│ │ │ ├── fd: (15)-->(21)
│ │ │ ├── ordering: +15
│ │ │ ├── scan supplier
│ │ │ │ ├── columns: s_suppkey:15!null s_comment:21!null
│ │ │ │ ├── key: (15)
│ │ │ │ ├── fd: (15)-->(21)
│ │ │ │ └── ordering: +15
│ │ │ └── filters
│ │ │ └── s_comment:21 LIKE '%Customer%Complaints%' [outer=(21), constraints=(/21: (/NULL - ])]
│ │ └── filters (true)
│ └── filters
│ ├── p_brand:9 != 'Brand#45' [outer=(9), constraints=(/9: (/NULL - /'Brand#45') [/e'Brand#45\x00' - ]; tight)]
│ ├── p_type:10 NOT LIKE 'MEDIUM POLISHED %' [outer=(10), constraints=(/10: (/NULL - ])]
│ └── p_size:11 IN (3, 9, 14, 19, 23, 36, 45, 49) [outer=(11), constraints=(/11: [/3 - /3] [/9 - /9] [/14 - /14] [/19 - /19] [/23 - /23] [/36 - /36] [/45 - /45] [/49 - /49]; tight)]
├── distinct-on
│ ├── columns: ps_suppkey:2!null p_brand:9!null p_type:10!null p_size:11!null
│ ├── grouping columns: ps_suppkey:2!null p_brand:9!null p_type:10!null p_size:11!null
│ ├── key: (2,9-11)
│ └── inner-join (lookup part)
│ ├── columns: ps_partkey:1!null ps_suppkey:2!null p_partkey:6!null p_brand:9!null p_type:10!null p_size:11!null
│ ├── key columns: [1] = [6]
│ ├── lookup columns are key
│ ├── key: (2,6)
│ ├── fd: (6)-->(9-11), (1)==(6), (6)==(1)
│ ├── anti-join (merge)
│ │ ├── columns: ps_partkey:1!null ps_suppkey:2!null
│ │ ├── left ordering: +2
│ │ ├── right ordering: +15
│ │ ├── key: (1,2)
│ │ ├── scan [email protected]_sk
│ │ │ ├── columns: ps_partkey:1!null ps_suppkey:2!null
│ │ │ ├── key: (1,2)
│ │ │ └── ordering: +2
│ │ ├── select
│ │ │ ├── columns: s_suppkey:15!null s_comment:21!null
│ │ │ ├── key: (15)
│ │ │ ├── fd: (15)-->(21)
│ │ │ ├── ordering: +15
│ │ │ ├── scan supplier
│ │ │ │ ├── columns: s_suppkey:15!null s_comment:21!null
│ │ │ │ ├── key: (15)
│ │ │ │ ├── fd: (15)-->(21)
│ │ │ │ └── ordering: +15
│ │ │ └── filters
│ │ │ └── s_comment:21 LIKE '%Customer%Complaints%' [outer=(21), constraints=(/21: (/NULL - ])]
│ │ └── filters (true)
│ └── filters
│ ├── p_brand:9 != 'Brand#45' [outer=(9), constraints=(/9: (/NULL - /'Brand#45') [/e'Brand#45\x00' - ]; tight)]
│ ├── p_type:10 NOT LIKE 'MEDIUM POLISHED %' [outer=(10), constraints=(/10: (/NULL - ])]
│ └── p_size:11 IN (3, 9, 14, 19, 23, 36, 45, 49) [outer=(11), constraints=(/11: [/3 - /3] [/9 - /9] [/14 - /14] [/19 - /19] [/23 - /23] [/36 - /36] [/45 - /45] [/49 - /49]; tight)]
└── aggregations
└── agg-distinct [as=count:22, outer=(2)]
└── count
└── ps_suppkey:2
└── count-rows [as=count:22]
# --------------------------------------------------
# Q17
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment