From 32d9973d220e7b91a6fe438a3756f4eb9cfb9549 Mon Sep 17 00:00:00 2001 From: Rebecca Taft Date: Tue, 27 Aug 2019 18:10:46 +0200 Subject: [PATCH] opt: calculate number of rows processed when costing lookup and merge joins This commit updates the costing of both lookup joins and merge joins to take into account the number of rows processed by the operator. This number may be larger than the number of output rows if an additional filter is applied as part of the ON condition that is not used to determine equality columns for the join. For example, consider the query `SELECT * FROM abc JOIN def ON a = e AND b = 3;` Assuming there is no index on b, if a lookup join is used to execute this query, the number of rows processed is actually the same as the query `SELECT * FROM abc JOIN def ON a = e;` The difference is that the filter b=3 must also be applied to every row in the first query. The coster now takes this into account when determining the cost of lookup joins and merge joins. Informs #34810 Release note: None --- .../opt/exec/execbuilder/testdata/lookup_join | 40 +- pkg/sql/opt/memo/logical_props_builder.go | 14 + pkg/sql/opt/memo/memo.go | 12 + pkg/sql/opt/memo/statistics_builder.go | 52 +- pkg/sql/opt/memo/testdata/stats/lookup-join | 44 +- pkg/sql/opt/memo/testdata/stats_quality/tpcc | 8 +- pkg/sql/opt/optgen/exprgen/testdata/join | 4 +- pkg/sql/opt/xform/coster.go | 38 +- pkg/sql/opt/xform/testdata/coster/join | 4 +- pkg/sql/opt/xform/testdata/coster/zone | 4 +- pkg/sql/opt/xform/testdata/external/nova | 1083 +++++++++-------- pkg/sql/opt/xform/testdata/external/tpcc | 8 +- .../xform/testdata/external/tpcc-later-stats | 8 +- .../opt/xform/testdata/external/tpcc-no-stats | 8 +- pkg/sql/opt/xform/testdata/rules/join | 4 +- pkg/sql/opt/xform/testdata/rules/join_order | 2 +- 16 files changed, 728 insertions(+), 605 deletions(-) diff --git a/pkg/sql/opt/exec/execbuilder/testdata/lookup_join b/pkg/sql/opt/exec/execbuilder/testdata/lookup_join index 7222951d027f..89f76169e5c6 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/lookup_join +++ b/pkg/sql/opt/exec/execbuilder/testdata/lookup_join @@ -217,25 +217,25 @@ ALTER TABLE authors INJECT STATISTICS '[ query TTTTT colnames EXPLAIN (VERBOSE) SELECT DISTINCT authors.name FROM books AS b1, books2 AS b2, authors WHERE b1.title = b2.title AND authors.book = b1.title AND b1.shelf <> b2.shelf ---- -tree field description columns ordering -distinct · · (name) weak-key(name) - │ distinct on name · · - └── render · · (name) · - │ render 0 name · · - └── hash-join · · (title, shelf, title, shelf, name, book) · - │ type inner · · - │ equality (title) = (book) · · - ├── lookup-join · · (title, shelf, title, shelf) · - │ │ table books2@primary · · - │ │ type inner · · - │ │ equality (title) = (title) · · - │ │ pred @2 != @4 · · - │ └── scan · · (title, shelf) · - │ table books@primary · · - │ spans ALL · · - └── scan · · (name, book) · -· table authors@primary · · -· spans ALL · · +tree field description columns ordering +distinct · · (name) weak-key(name) + │ distinct on name · · + └── render · · (name) · + │ render 0 name · · + └── lookup-join · · (name, book, title, shelf, title, shelf) · + │ table books2@primary · · + │ type inner · · + │ equality (title) = (title) · · + │ pred @4 != @6 · · + └── hash-join · · (name, book, title, shelf) · + │ type inner · · + │ equality (book) = (title) · · + ├── scan · · (name, book) · + │ table authors@primary · · + │ spans ALL · · + └── scan · · (title, shelf) · +· table books@primary · · +· spans ALL · · # Verify data placement. query TTTI colnames @@ -249,7 +249,7 @@ NULL NULL {5} 5 query T SELECT url FROM [EXPLAIN (DISTSQL) SELECT DISTINCT authors.name FROM books AS b1, books2 AS b2, authors WHERE b1.title = b2.title AND authors.book = b1.title AND b1.shelf <> b2.shelf] ---- -https://cockroachdb.github.io/distsqlplan/decode.html#eJyck89q3DAQh-99CndOCSjYku0cDAEdemhK2ZS0t7IHxZruqnE0RpKhJey7F9mlWZu10s1Rf76Zb362nsGSxo16Qg_Nd-DAoIYtg95Ri96Ti9vTpVv9C5qCgbH9EOL2lkFLDqF5hmBCh9DAhq6oz2tgoDEo043XDgxoCC-QD2qH0Fwf2FFhni78TT10eI9Ko8uLWXnonXlS7rd8IHr0wOBrr6xvsitgcDeEJpOcyRLWLPg5Fp_I2L8SPCEhgMFnosehz36SsRnZaBF9NpkU2fubTNbHdoLJksl61VG8NSlxWlINYR-_7OmsxKpHuerx0n6w5DQ61Mt_4PUrJ4b5qPw-ho4uL-ezdPgjXEh-eePMbh8upLj8N8N6kNU5QX4wPhjbhryad5Z8tX49q__KW7lH35P1-F-PpYjpoN7hlLanwbX4xVE7tpmWdyM3bmj0YTq9nha3djqKgscwT8IiDYskXM1gvoTLM2CxhKskXKe16yRcLODt4d2fAAAA__8CwK1z +https://cockroachdb.github.io/distsqlplan/decode.html#eJyck89q3DAQh-99CnVOCSjsyn9SEAR06KEpZbekvZU9KNZ0V42jMZIMLWHfvcgubGxipZujpPlG3_xsPYEjgxv9iAHkDxDAoYYdh85TgyGQT9tj0a35DXLNwbquj2l7x6EhjyCfINrYIkjY0BV1qxo4GIzatkPZkQP18QSFqPcI8vrInzUW-cbf9X2Ld6gN-tV60h46bx-1_6N0Hw_Jl8O3Trsg2RVw2PZRMiW4KmDJQ7zVQ7zscU_0sGRRLloUixany3tH3qBHM8_39ZIXRvmkw-EzWYd-VUwnafFnvFDF5Y23-0O8UOJykiRXJVfV4iTlOXkmgX9xlpk4k-AXooe-Y7_IOkZOMpWA7Yapir2_YerDyXFRrTpH7aMN0bomrqqpWKZ_Pen_ylu5w9CRC_hfj2WdviCaPY5_RKDeN_jVUzNcMy63AzdsGAxxPL0eF7duPEqCz2GRhcsJLOZwcQZczOEyC1d57SoL13m4zsLrGbw7vvsbAAD__5P3rXQ= query TTTTT colnames EXPLAIN (VERBOSE) SELECT a.name FROM authors AS a JOIN books2 AS b2 ON a.book = b2.title ORDER BY a.name diff --git a/pkg/sql/opt/memo/logical_props_builder.go b/pkg/sql/opt/memo/logical_props_builder.go index 46f5b1d6c083..c5e136e94b2f 100644 --- a/pkg/sql/opt/memo/logical_props_builder.go +++ b/pkg/sql/opt/memo/logical_props_builder.go @@ -1586,6 +1586,14 @@ func ensureLookupJoinInputProps(join *LookupJoinExpr, sb *statisticsBuilder) *pr if relational.OutputCols.Empty() { md := join.Memo().Metadata() relational.OutputCols = join.Cols.Difference(join.Input.Relational().OutputCols) + + // Include the key columns in the output columns. + index := md.Table(join.Table).Index(join.Index) + for i := range join.KeyCols { + indexColID := join.Table.ColumnID(index.Column(i).Ordinal) + relational.OutputCols.Add(indexColID) + } + relational.NotNullCols = tableNotNullCols(md, join.Table) relational.NotNullCols.IntersectionWith(relational.OutputCols) relational.Cardinality = props.AnyCardinality @@ -1679,6 +1687,8 @@ type joinPropsHelper struct { filterNotNullCols opt.ColSet filterIsTrue bool filterIsFalse bool + + selfJoinCols opt.ColSet } func (h *joinPropsHelper) init(b *logicalPropsBuilder, joinExpr RelExpr) { @@ -1702,6 +1712,10 @@ func (h *joinPropsHelper) init(b *logicalPropsBuilder, joinExpr RelExpr) { h.filterNotNullCols.Add(colID) h.filterNotNullCols.Add(indexColID) h.filtersFD.AddEquivalency(colID, indexColID) + if colID == indexColID { + // This can happen if an index join was converted into a lookup join. + h.selfJoinCols.Add(colID) + } } // Lookup join has implicit equality conditions on KeyCols. diff --git a/pkg/sql/opt/memo/memo.go b/pkg/sql/opt/memo/memo.go index 634091c028f2..fbe6d5b7468b 100644 --- a/pkg/sql/opt/memo/memo.go +++ b/pkg/sql/opt/memo/memo.go @@ -358,6 +358,18 @@ func (m *Memo) RequestColStat( return nil, false } +// RowsProcessed calculates and returns the number of rows processed by the +// relational expression. It is currently only supported for lookup joins and +// merge joins. +func (m *Memo) RowsProcessed(expr RelExpr) (_ float64, ok bool) { + // When SetRoot is called, the statistics builder may have been cleared. + // If this happens, we can't serve the request anymore. + if m.logPropsBuilder.sb.md != nil { + return m.logPropsBuilder.sb.rowsProcessed(expr), true + } + return 0, false +} + // NextWithID returns a not-yet-assigned identifier for a WITH expression. func (m *Memo) NextWithID() opt.WithID { m.curWithID++ diff --git a/pkg/sql/opt/memo/statistics_builder.go b/pkg/sql/opt/memo/statistics_builder.go index 821fb295cddb..feae3ddf13b2 100644 --- a/pkg/sql/opt/memo/statistics_builder.go +++ b/pkg/sql/opt/memo/statistics_builder.go @@ -259,6 +259,7 @@ func (sb *statisticsBuilder) colStatFromInput(colSet opt.ColSet, e RelExpr) *pro } else { leftProps = e.Child(0).(RelExpr).Relational() } + intersectsLeft := leftProps.OutputCols.Intersects(colSet) var intersectsRight bool if lookupJoin != nil { @@ -268,13 +269,11 @@ func (sb *statisticsBuilder) colStatFromInput(colSet opt.ColSet, e RelExpr) *pro } else { intersectsRight = e.Child(1).(RelExpr).Relational().OutputCols.Intersects(colSet) } + + // It's possible that colSet intersects both left and right if we have a + // lookup join that was converted from an index join, so check the left + // side first. if intersectsLeft { - if intersectsRight { - // TODO(radu): what if both sides have columns in colSet? - panic(errors.AssertionFailedf( - "colSet %v contains both left and right columns", log.Safe(colSet), - )) - } if zigzagJoin != nil { return sb.colStatTable(zigzagJoin.LeftTable, colSet) } @@ -901,7 +900,13 @@ func (sb *statisticsBuilder) buildJoin( // Calculate selectivity and row count // ----------------------------------- - s.RowCount = leftStats.RowCount * rightStats.RowCount + if h.rightProps.FuncDeps.ColsAreStrictKey(h.selfJoinCols) { + // This is like an index join. + s.RowCount = leftStats.RowCount + } else { + s.RowCount = leftStats.RowCount * rightStats.RowCount + equivReps.UnionWith(h.selfJoinCols) + } inputRowCount := s.RowCount s.ApplySelectivity(sb.selectivityFromDistinctCounts(constrainedCols, join, s)) s.ApplySelectivity(sb.selectivityFromEquivalencies(equivReps, &h.filtersFD, join, s)) @@ -2271,6 +2276,39 @@ func (sb *statisticsBuilder) shouldUseHistogram(relProps *props.Relational) bool return relProps.Cardinality.Max >= minCardinalityForHistogram } +// rowsProcessed calculates and returns the number of rows processed by the +// relational expression. It is currently only supported for lookup joins and +// merge joins. +func (sb *statisticsBuilder) rowsProcessed(e RelExpr) float64 { + switch t := e.(type) { + case *LookupJoinExpr: + if t.On.IsTrue() { + // If there are no additional ON filters, the number of rows processed + // equals the number of output rows. + return e.Relational().Stats.RowCount + } + + // Otherwise, we need to determine the row count of the join before the + // ON conditions are applied. + withoutOn := e.Memo().MemoizeLookupJoin(t.Input, nil /* on */, &t.LookupJoinPrivate) + return withoutOn.Relational().Stats.RowCount + + case *MergeJoinExpr: + if t.On.IsTrue() { + // If there are no additional ON filters, the number of rows processed + // equals the number of output rows. + return e.Relational().Stats.RowCount + } + + // Otherwise, we need to determine the row count of the join before the + // ON conditions are applied. + withoutOn := e.Memo().MemoizeMergeJoin(t.Left, t.Right, nil /* on */, &t.MergeJoinPrivate) + return withoutOn.Relational().Stats.RowCount + } + + panic(errors.AssertionFailedf("rowsProcessed not supported for operator type %v", log.Safe(e.Op()))) +} + func min(a float64, b float64) float64 { if a < b { return a diff --git a/pkg/sql/opt/memo/testdata/stats/lookup-join b/pkg/sql/opt/memo/testdata/stats/lookup-join index e09947c73bbd..fd4da10b371e 100644 --- a/pkg/sql/opt/memo/testdata/stats/lookup-join +++ b/pkg/sql/opt/memo/testdata/stats/lookup-join @@ -135,7 +135,7 @@ CREATE TABLE abc (a INT, b INT, c INT, PRIMARY KEY (a, c)) ---- exec-ddl -CREATE TABLE def (d INT, e INT, f INT, g FLOAT, PRIMARY KEY (f, e), INDEX e_idx (e) STORING (d)) +CREATE TABLE def (d INT, e INT, f INT, g FLOAT, PRIMARY KEY (f, e), INDEX e_idx (e) STORING (d), INDEX d_idx (d)) ---- # Set up the statistics as if the first table is much smaller than the second. @@ -152,6 +152,12 @@ ALTER TABLE abc INJECT STATISTICS '[ exec-ddl ALTER TABLE def INJECT STATISTICS '[ + { + "columns": ["d"], + "created_at": "2018-01-01 1:00:00.00000+00:00", + "row_count": 10000, + "distinct_count": 1000 + }, { "columns": ["e"], "created_at": "2018-01-01 1:00:00.00000+00:00", @@ -216,7 +222,7 @@ SELECT a, b, c, d, e, f FROM abc JOIN DEF ON a = f inner-join (lookup def) ├── columns: a:1(int!null) b:2(int) c:3(int!null) d:4(int) e:5(int!null) f:6(int!null) ├── key columns: [1] = [6] - ├── stats: [rows=100, distinct(1)=100, null(1)=0, distinct(2)=9.99954623, null(2)=1, distinct(3)=9.99954623, null(3)=0, distinct(4)=95.1671064, null(4)=1, distinct(5)=63.2138954, null(5)=0, distinct(6)=100, null(6)=0, distinct(2,5,6)=100, null(2,5,6)=1] + ├── stats: [rows=100, distinct(1)=100, null(1)=0, distinct(2)=9.99954623, null(2)=1, distinct(3)=9.99954623, null(3)=0, distinct(4)=95.1671064, null(4)=0, distinct(5)=63.2138954, null(5)=0, distinct(6)=100, null(6)=0, distinct(2,5,6)=100, null(2,5,6)=1] ├── key: (3,5,6) ├── fd: (1,3)-->(2), (5,6)-->(4), (1)==(6), (6)==(1) ├── scan abc @@ -228,18 +234,18 @@ inner-join (lookup def) # Check column statistics for double lookup join. opt colstat=7 -SELECT * FROM abc LEFT JOIN DEF ON a = e AND b = 3 +SELECT * FROM abc LEFT JOIN DEF ON a = d AND b = 3 ---- left-join (lookup def) ├── columns: a:1(int!null) b:2(int) c:3(int!null) d:4(int) e:5(int) f:6(int) g:7(float) ├── key columns: [6 5] = [6 5] - ├── stats: [rows=1000, distinct(5)=100, null(5)=0, distinct(7)=632.304575, null(7)=10] + ├── stats: [rows=100, distinct(4)=100, null(4)=0, distinct(7)=95.1671064, null(7)=1] ├── key: (1,3,5,6) ├── fd: (1,3)-->(2), (5,6)-->(4,7) - ├── left-join (lookup def@e_idx) + ├── left-join (lookup def@d_idx) │ ├── columns: a:1(int!null) b:2(int) c:3(int!null) d:4(int) e:5(int) f:6(int) - │ ├── key columns: [1] = [5] - │ ├── stats: [rows=1000, distinct(5)=100, null(5)=0] + │ ├── key columns: [1] = [4] + │ ├── stats: [rows=100, distinct(4)=100, null(4)=0] │ ├── key: (1,3,5,6) │ ├── fd: (1,3)-->(2), (5,6)-->(4) │ ├── scan abc @@ -250,3 +256,27 @@ left-join (lookup def) │ └── filters │ └── b = 3 [type=bool, outer=(2), constraints=(/2: [/3 - /3]; tight), fd=()-->(2)] └── filters (true) + +# The filter a=e is not very selective, so we do not expect a lookup join, even +# though there is an additional filter. +opt colstat=7 +SELECT * FROM abc LEFT JOIN DEF ON a = e AND b = 3 +---- +right-join (hash) + ├── columns: a:1(int!null) b:2(int) c:3(int!null) d:4(int) e:5(int) f:6(int) g:7(float) + ├── stats: [rows=1000, distinct(5)=100, null(5)=0, distinct(7)=632.304575, null(7)=10] + ├── key: (1,3,5,6) + ├── fd: (1,3)-->(2), (5,6)-->(4,7) + ├── scan def + │ ├── columns: d:4(int) e:5(int!null) f:6(int!null) g:7(float) + │ ├── stats: [rows=10000, distinct(5)=100, null(5)=0, distinct(7)=1000, null(7)=100] + │ ├── key: (5,6) + │ └── fd: (5,6)-->(4,7) + ├── scan abc + │ ├── columns: a:1(int!null) b:2(int) c:3(int!null) + │ ├── stats: [rows=100, distinct(1)=100, null(1)=0, distinct(2)=10, null(2)=1, distinct(3)=10, null(3)=0] + │ ├── key: (1,3) + │ └── fd: (1,3)-->(2) + └── filters + ├── a = e [type=bool, outer=(1,5), constraints=(/1: (/NULL - ]; /5: (/NULL - ]), fd=(1)==(5), (5)==(1)] + └── b = 3 [type=bool, outer=(2), constraints=(/2: [/3 - /3]; tight), fd=()-->(2)] diff --git a/pkg/sql/opt/memo/testdata/stats_quality/tpcc b/pkg/sql/opt/memo/testdata/stats_quality/tpcc index df66e06826e7..c19360e86307 100644 --- a/pkg/sql/opt/memo/testdata/stats_quality/tpcc +++ b/pkg/sql/opt/memo/testdata/stats_quality/tpcc @@ -614,7 +614,7 @@ scalar-group-by ├── columns: count:28(int) ├── cardinality: [1 - 1] ├── stats: [rows=1, distinct(28)=1, null(28)=0] - ├── cost: 1436.73853 + ├── cost: 1370.66482 ├── key: () ├── fd: ()-->(28) ├── prune: (28) @@ -623,7 +623,7 @@ scalar-group-by │ ├── columns: ol_o_id:1(int!null) ol_d_id:2(int!null) ol_w_id:3(int!null) ol_i_id:5(int!null) s_i_id:11(int!null) s_w_id:12(int!null) s_quantity:13(int!null) │ ├── key columns: [3 5] = [12 11] │ ├── stats: [rows=216.137889, distinct(1)=19.9995949, null(1)=0, distinct(2)=1, null(2)=0, distinct(3)=1, null(3)=0, distinct(5)=185.570315, null(5)=0, distinct(11)=185.570315, null(11)=0, distinct(12)=1, null(12)=0, distinct(13)=30.3089364, null(13)=0] - │ ├── cost: 1434.55715 + │ ├── cost: 1368.48344 │ ├── fd: ()-->(2,3,12), (11)-->(13), (5)==(11), (11)==(5), (3)==(12), (12)==(3) │ ├── interesting orderings: (+3,+2,-1) │ ├── scan order_line @@ -714,7 +714,7 @@ scalar-group-by ├── columns: count:22(int) ├── cardinality: [1 - 1] ├── stats: [rows=1, distinct(22)=1, null(22)=0] - ├── cost: 126.546667 + ├── cost: 126.613333 ├── key: () ├── fd: ()-->(22) ├── prune: (22) @@ -724,7 +724,7 @@ scalar-group-by │ ├── left ordering: +1 │ ├── right ordering: +11 │ ├── stats: [rows=3.33333333, distinct(1)=3.33333333, null(1)=0, distinct(9)=1, null(9)=0, distinct(11)=3.33333333, null(11)=0, distinct(21)=3.33333333, null(21)=0] - │ ├── cost: 126.493333 + │ ├── cost: 126.56 │ ├── key: (11) │ ├── fd: (1)-->(9), (11)-->(21), (1)==(11), (11)==(1) │ ├── scan warehouse diff --git a/pkg/sql/opt/optgen/exprgen/testdata/join b/pkg/sql/opt/optgen/exprgen/testdata/join index 0b7907a790d2..2cdbfdaa50be 100644 --- a/pkg/sql/opt/optgen/exprgen/testdata/join +++ b/pkg/sql/opt/optgen/exprgen/testdata/join @@ -47,8 +47,8 @@ expr left-join (lookup abc@ab) ├── columns: t.public.abc.a:5(int) t.public.abc.b:6(int) ├── key columns: [5] = [5] - ├── stats: [rows=333333.333, distinct(5)=100, null(5)=3333.33333] - ├── cost: 691726.707 + ├── stats: [rows=3333.33333, distinct(5)=100, null(5)=33.3333333] + ├── cost: 25660.04 ├── scan t.public.def │ ├── columns: t.public.def.d:1(int) t.public.def.e:2(int) │ ├── stats: [rows=1000, distinct(2)=100, null(2)=10] diff --git a/pkg/sql/opt/xform/coster.go b/pkg/sql/opt/xform/coster.go index ea5448887ed4..d5b008707eb0 100644 --- a/pkg/sql/opt/xform/coster.go +++ b/pkg/sql/opt/xform/coster.go @@ -360,9 +360,14 @@ func (c *coster) computeMergeJoinCost(join *memo.MergeJoinExpr) memo.Cost { cost := memo.Cost(leftRowCount+rightRowCount) * cpuCostFactor // Add the CPU cost of emitting the rows. - // TODO(radu): ideally we would have an estimate of how many rows we actually - // have to run the ON condition on. - cost += memo.Cost(join.Relational().Stats.RowCount) * cpuCostFactor + rowsProcessed, ok := c.mem.RowsProcessed(join) + if !ok { + // We shouldn't ever get here. Since we don't allow the memo + // to be optimized twice, the coster should never be used after + // logPropsBuilder.clear() is called. + panic(errors.AssertionFailedf("could not get rows processed for merge join")) + } + cost += memo.Cost(rowsProcessed) * cpuCostFactor return cost } @@ -402,11 +407,14 @@ func (c *coster) computeLookupJoinCost(join *memo.LookupJoinExpr) memo.Cost { // a=x), and another lookup join on an index on x,y. The latter is definitely // preferable (the former could generate a lot of internal results that are // then discarded). - // - // TODO(radu): we should take into account that the "internal" row count is - // higher, according to the selectivities of the conditions. Unfortunately - // this is very tricky, in particular because of left-over conditions that are - // not selective. + perRowCost += cpuCostFactor * memo.Cost(len(join.On)) + // We also add a constant "setup" cost per ON condition. Without this, the + // adjustment above can be inconsequential when the RowCount is too small. + cost += cpuCostFactor * memo.Cost(len(join.On)) + + // Take into account that the "internal" row count is higher, according to + // the selectivities of the conditions. In particular, we need to ignore + // left-over conditions that are not selective. // For example: // ab JOIN xy ON a=x AND x=10 // becomes (during normalization): @@ -417,12 +425,14 @@ func (c *coster) computeLookupJoinCost(join *memo.LookupJoinExpr) memo.Cost { // TODO(radu): this should be extended to all join types. It's tricky for hash // joins where we don't have the equality and leftover filters readily // available. - perRowCost += cpuCostFactor * memo.Cost(len(join.On)) - // We also add a constant "setup" cost per ON condition. Without this, the - // adjustment above can be inconsequential when the RowCount is too small. - cost += cpuCostFactor * memo.Cost(len(join.On)) - - cost += memo.Cost(join.Relational().Stats.RowCount) * perRowCost + rowsProcessed, ok := c.mem.RowsProcessed(join) + if !ok { + // We shouldn't ever get here. Since we don't allow the memo + // to be optimized twice, the coster should never be used after + // logPropsBuilder.clear() is called. + panic(errors.AssertionFailedf("could not get rows processed for lookup join")) + } + cost += memo.Cost(rowsProcessed) * perRowCost return cost } diff --git a/pkg/sql/opt/xform/testdata/coster/join b/pkg/sql/opt/xform/testdata/coster/join index 584fd4d8482c..666e3cf7a13c 100644 --- a/pkg/sql/opt/xform/testdata/coster/join +++ b/pkg/sql/opt/xform/testdata/coster/join @@ -225,13 +225,13 @@ WHERE w = 'foo' AND x = '2AB23800-06B1-4E19-A3BB-DF3768B808D2' project ├── columns: w:1(string!null) x:2(uuid!null) y:3(uuid!null) z:4(string!null) ├── stats: [rows=500.488759] - ├── cost: 1566.10128 + ├── cost: 1565.07489 ├── fd: ()-->(1,2) └── inner-join (lookup abcde@idx_abcd) ├── columns: w:1(string!null) x:2(uuid!null) y:3(uuid!null) z:4(string!null) a:6(string!null) b:7(uuid!null) c:8(uuid!null) ├── key columns: [1 2 3] = [6 7 8] ├── stats: [rows=500.488759, distinct(1)=1, null(1)=0, distinct(2)=1, null(2)=0, distinct(3)=25, null(3)=0, distinct(4)=10, null(4)=0, distinct(6)=1, null(6)=0, distinct(7)=1, null(7)=0, distinct(8)=25, null(8)=0] - ├── cost: 1561.08639 + ├── cost: 1560.06 ├── fd: ()-->(1,2,6,7), (1)==(6), (6)==(1), (2)==(7), (7)==(2), (3)==(8), (8)==(3) ├── select │ ├── columns: w:1(string!null) x:2(uuid!null) y:3(uuid!null) z:4(string!null) diff --git a/pkg/sql/opt/xform/testdata/coster/zone b/pkg/sql/opt/xform/testdata/coster/zone index eee9c3da3caf..51440e600921 100644 --- a/pkg/sql/opt/xform/testdata/coster/zone +++ b/pkg/sql/opt/xform/testdata/coster/zone @@ -367,7 +367,7 @@ inner-join (lookup xy@y2) ├── flags: no-merge-join;no-hash-join ├── key columns: [2] = [5] ├── stats: [rows=98.01, distinct(1)=9.9, null(1)=0, distinct(2)=1, null(2)=0, distinct(4)=9.9, null(4)=0, distinct(5)=1, null(5)=0] - ├── cost: 251.0445 + ├── cost: 253.074 ├── key: (1,4) ├── fd: ()-->(2,5), (1)-->(3), (2,3)~~>(1), (2)==(5), (5)==(2) ├── prune: (1,3,4) @@ -405,7 +405,7 @@ inner-join (lookup xy@y1) ├── flags: no-merge-join;no-hash-join ├── key columns: [2] = [5] ├── stats: [rows=98.01, distinct(1)=9.9, null(1)=0, distinct(2)=1, null(2)=0, distinct(4)=9.9, null(4)=0, distinct(5)=1, null(5)=0] - ├── cost: 251.0445 + ├── cost: 253.074 ├── key: (1,4) ├── fd: ()-->(2,5), (1)-->(3), (2,3)~~>(1), (2)==(5), (5)==(2) ├── prune: (1,3,4) diff --git a/pkg/sql/opt/xform/testdata/external/nova b/pkg/sql/opt/xform/testdata/external/nova index 551e1605921e..e20b93fe81bb 100644 --- a/pkg/sql/opt/xform/testdata/external/nova +++ b/pkg/sql/opt/xform/testdata/external/nova @@ -947,121 +947,124 @@ project ├── side-effects, has-placeholder ├── key: (1,28) ├── fd: (1)-->(2-16), (7,13)~~>(1-6,8-12,14-16), (2,13)-->(1,3-12,14-16), (28)-->(29-35), (29,31,32)~~>(28,30,33-35) - └── left-join (lookup instance_type_extra_specs) + └── right-join (hash) ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) instance_type_extra_specs_1.id:28(int) key:29(string) value:30(string) instance_type_extra_specs_1.instance_type_id:31(int) instance_type_extra_specs_1.deleted:32(bool) instance_type_extra_specs_1.deleted_at:33(timestamp) instance_type_extra_specs_1.created_at:34(timestamp) instance_type_extra_specs_1.updated_at:35(timestamp) - ├── key columns: [28] = [28] ├── side-effects, has-placeholder ├── key: (1,28) ├── fd: (1)-->(2-16,26), (7,13)~~>(1-6,8-12,14-16), (2,13)-->(1,3-12,14-16), (28)-->(29-35), (29,31,32)~~>(28,30,33-35) - ├── left-join (lookup instance_type_extra_specs@secondary) - │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) instance_type_extra_specs_1.id:28(int) key:29(string) instance_type_extra_specs_1.instance_type_id:31(int) instance_type_extra_specs_1.deleted:32(bool) - │ ├── key columns: [1] = [31] + ├── select + │ ├── columns: instance_type_extra_specs_1.id:28(int!null) key:29(string) value:30(string) instance_type_extra_specs_1.instance_type_id:31(int!null) instance_type_extra_specs_1.deleted:32(bool!null) instance_type_extra_specs_1.deleted_at:33(timestamp) instance_type_extra_specs_1.created_at:34(timestamp) instance_type_extra_specs_1.updated_at:35(timestamp) + │ ├── has-placeholder + │ ├── key: (28) + │ ├── fd: (28)-->(29-35), (29,31,32)~~>(28,30,33-35) + │ ├── scan instance_type_extra_specs_1 + │ │ ├── columns: instance_type_extra_specs_1.id:28(int!null) key:29(string) value:30(string) instance_type_extra_specs_1.instance_type_id:31(int!null) instance_type_extra_specs_1.deleted:32(bool) instance_type_extra_specs_1.deleted_at:33(timestamp) instance_type_extra_specs_1.created_at:34(timestamp) instance_type_extra_specs_1.updated_at:35(timestamp) + │ │ ├── key: (28) + │ │ └── fd: (28)-->(29-35), (29,31,32)~~>(28,30,33-35) + │ └── filters + │ └── instance_type_extra_specs_1.deleted = $7 [type=bool, outer=(32), constraints=(/32: (/NULL - ])] + ├── limit + │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) │ ├── side-effects, has-placeholder - │ ├── key: (1,28) - │ ├── fd: (1)-->(2-16,26), (7,13)~~>(1-6,8-12,14-16), (2,13)-->(1,3-12,14-16), (28)-->(29,31,32), (29,31,32)~~>(28) - │ ├── limit + │ ├── key: (1) + │ ├── fd: (1)-->(2-16,26), (7,13)~~>(1-6,8-12,14-16), (2,13)-->(1,3-12,14-16) + │ ├── offset │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) - │ │ ├── side-effects, has-placeholder + │ │ ├── has-placeholder │ │ ├── key: (1) │ │ ├── fd: (1)-->(2-16,26), (7,13)~~>(1-6,8-12,14-16), (2,13)-->(1,3-12,14-16) - │ │ ├── offset + │ │ ├── select │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) │ │ │ ├── has-placeholder │ │ │ ├── key: (1) │ │ │ ├── fd: (1)-->(2-16,26), (7,13)~~>(1-6,8-12,14-16), (2,13)-->(1,3-12,14-16) - │ │ │ ├── select + │ │ │ ├── group-by │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) + │ │ │ │ ├── grouping columns: instance_types.id:1(int!null) + │ │ │ │ ├── internal-ordering: +1 │ │ │ │ ├── has-placeholder │ │ │ │ ├── key: (1) │ │ │ │ ├── fd: (1)-->(2-16,26), (7,13)~~>(1-6,8-12,14-16), (2,13)-->(1,3-12,14-16) - │ │ │ │ ├── group-by - │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) - │ │ │ │ │ ├── grouping columns: instance_types.id:1(int!null) - │ │ │ │ │ ├── internal-ordering: +1 + │ │ │ │ ├── left-join (merge) + │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string!null) memory_mb:3(int!null) vcpus:4(int!null) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int!null) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool!null) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) instance_type_projects.instance_type_id:18(int) true:25(bool) + │ │ │ │ │ ├── left ordering: +1 + │ │ │ │ │ ├── right ordering: +18 │ │ │ │ │ ├── has-placeholder - │ │ │ │ │ ├── key: (1) - │ │ │ │ │ ├── fd: (1)-->(2-16,26), (7,13)~~>(1-6,8-12,14-16), (2,13)-->(1,3-12,14-16) - │ │ │ │ │ ├── left-join (merge) - │ │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string!null) memory_mb:3(int!null) vcpus:4(int!null) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int!null) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool!null) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) instance_type_projects.instance_type_id:18(int) true:25(bool) - │ │ │ │ │ │ ├── left ordering: +1 - │ │ │ │ │ │ ├── right ordering: +18 + │ │ │ │ │ ├── fd: (1)-->(2-16), (7,13)~~>(1-6,8-12,14-16), (2,13)-->(1,3-12,14-16), ()~~>(25) + │ │ │ │ │ ├── ordering: +1 + │ │ │ │ │ ├── select + │ │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string!null) memory_mb:3(int!null) vcpus:4(int!null) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int!null) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool!null) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) │ │ │ │ │ │ ├── has-placeholder - │ │ │ │ │ │ ├── fd: (1)-->(2-16), (7,13)~~>(1-6,8-12,14-16), (2,13)-->(1,3-12,14-16), ()~~>(25) + │ │ │ │ │ │ ├── key: (1) + │ │ │ │ │ │ ├── fd: (1)-->(2-16), (7,13)~~>(1-6,8-12,14-16), (2,13)-->(1,3-12,14-16) │ │ │ │ │ │ ├── ordering: +1 + │ │ │ │ │ │ ├── scan instance_types + │ │ │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int!null) vcpus:4(int!null) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int!null) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) + │ │ │ │ │ │ │ ├── key: (1) + │ │ │ │ │ │ │ ├── fd: (1)-->(2-16), (7,13)~~>(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) + │ │ │ │ │ │ │ └── ordering: +1 + │ │ │ │ │ │ └── filters + │ │ │ │ │ │ ├── instance_types.deleted = $1 [type=bool, outer=(13), constraints=(/13: (/NULL - ])] + │ │ │ │ │ │ └── name = $4 [type=bool, outer=(2), constraints=(/2: (/NULL - ])] + │ │ │ │ │ ├── project + │ │ │ │ │ │ ├── columns: true:25(bool!null) instance_type_projects.instance_type_id:18(int!null) + │ │ │ │ │ │ ├── has-placeholder + │ │ │ │ │ │ ├── fd: ()-->(25) + │ │ │ │ │ │ ├── ordering: +18 opt(25) [actual: +18] │ │ │ │ │ │ ├── select - │ │ │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string!null) memory_mb:3(int!null) vcpus:4(int!null) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int!null) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool!null) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) + │ │ │ │ │ │ │ ├── columns: instance_type_projects.instance_type_id:18(int!null) project_id:19(string!null) instance_type_projects.deleted:20(bool!null) │ │ │ │ │ │ │ ├── has-placeholder - │ │ │ │ │ │ │ ├── key: (1) - │ │ │ │ │ │ │ ├── fd: (1)-->(2-16), (7,13)~~>(1-6,8-12,14-16), (2,13)-->(1,3-12,14-16) - │ │ │ │ │ │ │ ├── ordering: +1 - │ │ │ │ │ │ │ ├── scan instance_types - │ │ │ │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int!null) vcpus:4(int!null) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int!null) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) - │ │ │ │ │ │ │ │ ├── key: (1) - │ │ │ │ │ │ │ │ ├── fd: (1)-->(2-16), (7,13)~~>(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) - │ │ │ │ │ │ │ │ └── ordering: +1 + │ │ │ │ │ │ │ ├── key: (18-20) + │ │ │ │ │ │ │ ├── ordering: +18 + │ │ │ │ │ │ │ ├── scan instance_type_projects@secondary + │ │ │ │ │ │ │ │ ├── columns: instance_type_projects.instance_type_id:18(int!null) project_id:19(string) instance_type_projects.deleted:20(bool) + │ │ │ │ │ │ │ │ ├── lax-key: (18-20) + │ │ │ │ │ │ │ │ └── ordering: +18 │ │ │ │ │ │ │ └── filters - │ │ │ │ │ │ │ ├── instance_types.deleted = $1 [type=bool, outer=(13), constraints=(/13: (/NULL - ])] - │ │ │ │ │ │ │ └── name = $4 [type=bool, outer=(2), constraints=(/2: (/NULL - ])] - │ │ │ │ │ │ ├── project - │ │ │ │ │ │ │ ├── columns: true:25(bool!null) instance_type_projects.instance_type_id:18(int!null) - │ │ │ │ │ │ │ ├── has-placeholder - │ │ │ │ │ │ │ ├── fd: ()-->(25) - │ │ │ │ │ │ │ ├── ordering: +18 opt(25) [actual: +18] - │ │ │ │ │ │ │ ├── select - │ │ │ │ │ │ │ │ ├── columns: instance_type_projects.instance_type_id:18(int!null) project_id:19(string!null) instance_type_projects.deleted:20(bool!null) - │ │ │ │ │ │ │ │ ├── has-placeholder - │ │ │ │ │ │ │ │ ├── key: (18-20) - │ │ │ │ │ │ │ │ ├── ordering: +18 - │ │ │ │ │ │ │ │ ├── scan instance_type_projects@secondary - │ │ │ │ │ │ │ │ │ ├── columns: instance_type_projects.instance_type_id:18(int!null) project_id:19(string) instance_type_projects.deleted:20(bool) - │ │ │ │ │ │ │ │ │ ├── lax-key: (18-20) - │ │ │ │ │ │ │ │ │ └── ordering: +18 - │ │ │ │ │ │ │ │ └── filters - │ │ │ │ │ │ │ │ ├── instance_type_projects.deleted = $2 [type=bool, outer=(20), constraints=(/20: (/NULL - ])] - │ │ │ │ │ │ │ │ └── project_id = $3 [type=bool, outer=(19), constraints=(/19: (/NULL - ])] - │ │ │ │ │ │ │ └── projections - │ │ │ │ │ │ │ └── true [type=bool] - │ │ │ │ │ │ └── filters (true) - │ │ │ │ │ └── aggregations - │ │ │ │ │ ├── const-not-null-agg [type=bool, outer=(25)] - │ │ │ │ │ │ └── variable: true [type=bool] - │ │ │ │ │ ├── const-agg [type=string, outer=(2)] - │ │ │ │ │ │ └── variable: name [type=string] - │ │ │ │ │ ├── const-agg [type=int, outer=(3)] - │ │ │ │ │ │ └── variable: memory_mb [type=int] - │ │ │ │ │ ├── const-agg [type=int, outer=(4)] - │ │ │ │ │ │ └── variable: vcpus [type=int] - │ │ │ │ │ ├── const-agg [type=int, outer=(5)] - │ │ │ │ │ │ └── variable: root_gb [type=int] - │ │ │ │ │ ├── const-agg [type=int, outer=(6)] - │ │ │ │ │ │ └── variable: ephemeral_gb [type=int] - │ │ │ │ │ ├── const-agg [type=string, outer=(7)] - │ │ │ │ │ │ └── variable: flavorid [type=string] - │ │ │ │ │ ├── const-agg [type=int, outer=(8)] - │ │ │ │ │ │ └── variable: swap [type=int] - │ │ │ │ │ ├── const-agg [type=float, outer=(9)] - │ │ │ │ │ │ └── variable: rxtx_factor [type=float] - │ │ │ │ │ ├── const-agg [type=int, outer=(10)] - │ │ │ │ │ │ └── variable: vcpu_weight [type=int] - │ │ │ │ │ ├── const-agg [type=bool, outer=(11)] - │ │ │ │ │ │ └── variable: disabled [type=bool] - │ │ │ │ │ ├── const-agg [type=bool, outer=(12)] - │ │ │ │ │ │ └── variable: is_public [type=bool] - │ │ │ │ │ ├── const-agg [type=bool, outer=(13)] - │ │ │ │ │ │ └── variable: instance_types.deleted [type=bool] - │ │ │ │ │ ├── const-agg [type=timestamp, outer=(14)] - │ │ │ │ │ │ └── variable: instance_types.deleted_at [type=timestamp] - │ │ │ │ │ ├── const-agg [type=timestamp, outer=(15)] - │ │ │ │ │ │ └── variable: instance_types.created_at [type=timestamp] - │ │ │ │ │ └── const-agg [type=timestamp, outer=(16)] - │ │ │ │ │ └── variable: instance_types.updated_at [type=timestamp] - │ │ │ │ └── filters - │ │ │ │ └── (is_public = true) OR (true_agg IS NOT NULL) [type=bool, outer=(12,26)] - │ │ │ └── placeholder: $5 [type=int] - │ │ └── placeholder: $6 [type=int] - │ └── filters - │ └── instance_type_extra_specs_1.deleted = $7 [type=bool, outer=(32), constraints=(/32: (/NULL - ])] - └── filters (true) + │ │ │ │ │ │ │ ├── instance_type_projects.deleted = $2 [type=bool, outer=(20), constraints=(/20: (/NULL - ])] + │ │ │ │ │ │ │ └── project_id = $3 [type=bool, outer=(19), constraints=(/19: (/NULL - ])] + │ │ │ │ │ │ └── projections + │ │ │ │ │ │ └── true [type=bool] + │ │ │ │ │ └── filters (true) + │ │ │ │ └── aggregations + │ │ │ │ ├── const-not-null-agg [type=bool, outer=(25)] + │ │ │ │ │ └── variable: true [type=bool] + │ │ │ │ ├── const-agg [type=string, outer=(2)] + │ │ │ │ │ └── variable: name [type=string] + │ │ │ │ ├── const-agg [type=int, outer=(3)] + │ │ │ │ │ └── variable: memory_mb [type=int] + │ │ │ │ ├── const-agg [type=int, outer=(4)] + │ │ │ │ │ └── variable: vcpus [type=int] + │ │ │ │ ├── const-agg [type=int, outer=(5)] + │ │ │ │ │ └── variable: root_gb [type=int] + │ │ │ │ ├── const-agg [type=int, outer=(6)] + │ │ │ │ │ └── variable: ephemeral_gb [type=int] + │ │ │ │ ├── const-agg [type=string, outer=(7)] + │ │ │ │ │ └── variable: flavorid [type=string] + │ │ │ │ ├── const-agg [type=int, outer=(8)] + │ │ │ │ │ └── variable: swap [type=int] + │ │ │ │ ├── const-agg [type=float, outer=(9)] + │ │ │ │ │ └── variable: rxtx_factor [type=float] + │ │ │ │ ├── const-agg [type=int, outer=(10)] + │ │ │ │ │ └── variable: vcpu_weight [type=int] + │ │ │ │ ├── const-agg [type=bool, outer=(11)] + │ │ │ │ │ └── variable: disabled [type=bool] + │ │ │ │ ├── const-agg [type=bool, outer=(12)] + │ │ │ │ │ └── variable: is_public [type=bool] + │ │ │ │ ├── const-agg [type=bool, outer=(13)] + │ │ │ │ │ └── variable: instance_types.deleted [type=bool] + │ │ │ │ ├── const-agg [type=timestamp, outer=(14)] + │ │ │ │ │ └── variable: instance_types.deleted_at [type=timestamp] + │ │ │ │ ├── const-agg [type=timestamp, outer=(15)] + │ │ │ │ │ └── variable: instance_types.created_at [type=timestamp] + │ │ │ │ └── const-agg [type=timestamp, outer=(16)] + │ │ │ │ └── variable: instance_types.updated_at [type=timestamp] + │ │ │ └── filters + │ │ │ └── (is_public = true) OR (true_agg IS NOT NULL) [type=bool, outer=(12,26)] + │ │ └── placeholder: $5 [type=int] + │ └── placeholder: $6 [type=int] + └── filters + └── instance_type_extra_specs_1.instance_type_id = instance_types.id [type=bool, outer=(1,31), constraints=(/1: (/NULL - ]; /31: (/NULL - ]), fd=(1)==(31), (31)==(1)] opt select anon_1.instance_types_created_at as anon_1_instance_types_created_at, @@ -1125,122 +1128,125 @@ project ├── side-effects, has-placeholder ├── key: (1,28) ├── fd: (1)-->(2-16), (7,13)~~>(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16), (28)-->(29-35), (29,31,32)~~>(28,30,33-35) - └── left-join (lookup instance_type_extra_specs) + └── right-join (hash) ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) instance_type_extra_specs_1.id:28(int) key:29(string) value:30(string) instance_type_extra_specs_1.instance_type_id:31(int) instance_type_extra_specs_1.deleted:32(bool) instance_type_extra_specs_1.deleted_at:33(timestamp) instance_type_extra_specs_1.created_at:34(timestamp) instance_type_extra_specs_1.updated_at:35(timestamp) - ├── key columns: [28] = [28] ├── side-effects, has-placeholder ├── key: (1,28) ├── fd: (1)-->(2-16,26), (7,13)~~>(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16), (28)-->(29-35), (29,31,32)~~>(28,30,33-35) - ├── left-join (lookup instance_type_extra_specs@secondary) - │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) instance_type_extra_specs_1.id:28(int) key:29(string) instance_type_extra_specs_1.instance_type_id:31(int) instance_type_extra_specs_1.deleted:32(bool) - │ ├── key columns: [1] = [31] + ├── select + │ ├── columns: instance_type_extra_specs_1.id:28(int!null) key:29(string) value:30(string) instance_type_extra_specs_1.instance_type_id:31(int!null) instance_type_extra_specs_1.deleted:32(bool!null) instance_type_extra_specs_1.deleted_at:33(timestamp) instance_type_extra_specs_1.created_at:34(timestamp) instance_type_extra_specs_1.updated_at:35(timestamp) + │ ├── has-placeholder + │ ├── key: (28) + │ ├── fd: (28)-->(29-35), (29,31,32)~~>(28,30,33-35) + │ ├── scan instance_type_extra_specs_1 + │ │ ├── columns: instance_type_extra_specs_1.id:28(int!null) key:29(string) value:30(string) instance_type_extra_specs_1.instance_type_id:31(int!null) instance_type_extra_specs_1.deleted:32(bool) instance_type_extra_specs_1.deleted_at:33(timestamp) instance_type_extra_specs_1.created_at:34(timestamp) instance_type_extra_specs_1.updated_at:35(timestamp) + │ │ ├── key: (28) + │ │ └── fd: (28)-->(29-35), (29,31,32)~~>(28,30,33-35) + │ └── filters + │ └── instance_type_extra_specs_1.deleted = $7 [type=bool, outer=(32), constraints=(/32: (/NULL - ])] + ├── limit + │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) │ ├── side-effects, has-placeholder - │ ├── key: (1,28) - │ ├── fd: (1)-->(2-16,26), (7,13)~~>(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16), (28)-->(29,31,32), (29,31,32)~~>(28) - │ ├── limit + │ ├── key: (1) + │ ├── fd: (1)-->(2-16,26), (7,13)~~>(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) + │ ├── offset │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) - │ │ ├── side-effects, has-placeholder + │ │ ├── has-placeholder │ │ ├── key: (1) │ │ ├── fd: (1)-->(2-16,26), (7,13)~~>(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) - │ │ ├── offset + │ │ ├── select │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) │ │ │ ├── has-placeholder │ │ │ ├── key: (1) │ │ │ ├── fd: (1)-->(2-16,26), (7,13)~~>(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) - │ │ │ ├── select + │ │ │ ├── group-by │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) + │ │ │ │ ├── grouping columns: instance_types.id:1(int!null) + │ │ │ │ ├── internal-ordering: +1 │ │ │ │ ├── has-placeholder │ │ │ │ ├── key: (1) │ │ │ │ ├── fd: (1)-->(2-16,26), (7,13)~~>(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) - │ │ │ │ ├── group-by - │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) - │ │ │ │ │ ├── grouping columns: instance_types.id:1(int!null) - │ │ │ │ │ ├── internal-ordering: +1 + │ │ │ │ ├── left-join (merge) + │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int!null) vcpus:4(int!null) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int!null) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool!null) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) instance_type_projects.instance_type_id:18(int) true:25(bool) + │ │ │ │ │ ├── left ordering: +1 + │ │ │ │ │ ├── right ordering: +18 │ │ │ │ │ ├── has-placeholder - │ │ │ │ │ ├── key: (1) - │ │ │ │ │ ├── fd: (1)-->(2-16,26), (7,13)~~>(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) - │ │ │ │ │ ├── left-join (merge) - │ │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int!null) vcpus:4(int!null) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int!null) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool!null) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) instance_type_projects.instance_type_id:18(int) true:25(bool) - │ │ │ │ │ │ ├── left ordering: +1 - │ │ │ │ │ │ ├── right ordering: +18 + │ │ │ │ │ ├── fd: (1)-->(2-16), (7,13)~~>(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16), ()~~>(25) + │ │ │ │ │ ├── ordering: +1 + │ │ │ │ │ ├── select + │ │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int!null) vcpus:4(int!null) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int!null) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool!null) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) │ │ │ │ │ │ ├── has-placeholder - │ │ │ │ │ │ ├── fd: (1)-->(2-16), (7,13)~~>(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16), ()~~>(25) + │ │ │ │ │ │ ├── key: (1) + │ │ │ │ │ │ ├── fd: (1)-->(2-16), (7,13)~~>(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) │ │ │ │ │ │ ├── ordering: +1 - │ │ │ │ │ │ ├── select - │ │ │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int!null) vcpus:4(int!null) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int!null) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool!null) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) - │ │ │ │ │ │ │ ├── has-placeholder + │ │ │ │ │ │ ├── scan instance_types + │ │ │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int!null) vcpus:4(int!null) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int!null) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) │ │ │ │ │ │ │ ├── key: (1) │ │ │ │ │ │ │ ├── fd: (1)-->(2-16), (7,13)~~>(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) - │ │ │ │ │ │ │ ├── ordering: +1 - │ │ │ │ │ │ │ ├── scan instance_types - │ │ │ │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int!null) vcpus:4(int!null) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int!null) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) - │ │ │ │ │ │ │ │ ├── key: (1) - │ │ │ │ │ │ │ │ ├── fd: (1)-->(2-16), (7,13)~~>(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) - │ │ │ │ │ │ │ │ └── ordering: +1 - │ │ │ │ │ │ │ └── filters - │ │ │ │ │ │ │ ├── instance_types.id = $4 [type=bool, outer=(1), constraints=(/1: (/NULL - ])] - │ │ │ │ │ │ │ └── instance_types.deleted = $1 [type=bool, outer=(13), constraints=(/13: (/NULL - ])] - │ │ │ │ │ │ ├── project - │ │ │ │ │ │ │ ├── columns: true:25(bool!null) instance_type_projects.instance_type_id:18(int!null) + │ │ │ │ │ │ │ └── ordering: +1 + │ │ │ │ │ │ └── filters + │ │ │ │ │ │ ├── instance_types.id = $4 [type=bool, outer=(1), constraints=(/1: (/NULL - ])] + │ │ │ │ │ │ └── instance_types.deleted = $1 [type=bool, outer=(13), constraints=(/13: (/NULL - ])] + │ │ │ │ │ ├── project + │ │ │ │ │ │ ├── columns: true:25(bool!null) instance_type_projects.instance_type_id:18(int!null) + │ │ │ │ │ │ ├── has-placeholder + │ │ │ │ │ │ ├── fd: ()-->(25) + │ │ │ │ │ │ ├── ordering: +18 opt(25) [actual: +18] + │ │ │ │ │ │ ├── select + │ │ │ │ │ │ │ ├── columns: instance_type_projects.instance_type_id:18(int!null) project_id:19(string!null) instance_type_projects.deleted:20(bool!null) │ │ │ │ │ │ │ ├── has-placeholder - │ │ │ │ │ │ │ ├── fd: ()-->(25) - │ │ │ │ │ │ │ ├── ordering: +18 opt(25) [actual: +18] - │ │ │ │ │ │ │ ├── select - │ │ │ │ │ │ │ │ ├── columns: instance_type_projects.instance_type_id:18(int!null) project_id:19(string!null) instance_type_projects.deleted:20(bool!null) - │ │ │ │ │ │ │ │ ├── has-placeholder - │ │ │ │ │ │ │ │ ├── key: (18-20) - │ │ │ │ │ │ │ │ ├── ordering: +18 - │ │ │ │ │ │ │ │ ├── scan instance_type_projects@secondary - │ │ │ │ │ │ │ │ │ ├── columns: instance_type_projects.instance_type_id:18(int!null) project_id:19(string) instance_type_projects.deleted:20(bool) - │ │ │ │ │ │ │ │ │ ├── lax-key: (18-20) - │ │ │ │ │ │ │ │ │ └── ordering: +18 - │ │ │ │ │ │ │ │ └── filters - │ │ │ │ │ │ │ │ ├── instance_type_projects.deleted = $2 [type=bool, outer=(20), constraints=(/20: (/NULL - ])] - │ │ │ │ │ │ │ │ ├── project_id = $3 [type=bool, outer=(19), constraints=(/19: (/NULL - ])] - │ │ │ │ │ │ │ │ └── instance_type_projects.instance_type_id = $4 [type=bool, outer=(18), constraints=(/18: (/NULL - ])] - │ │ │ │ │ │ │ └── projections - │ │ │ │ │ │ │ └── true [type=bool] - │ │ │ │ │ │ └── filters (true) - │ │ │ │ │ └── aggregations - │ │ │ │ │ ├── const-not-null-agg [type=bool, outer=(25)] - │ │ │ │ │ │ └── variable: true [type=bool] - │ │ │ │ │ ├── const-agg [type=string, outer=(2)] - │ │ │ │ │ │ └── variable: name [type=string] - │ │ │ │ │ ├── const-agg [type=int, outer=(3)] - │ │ │ │ │ │ └── variable: memory_mb [type=int] - │ │ │ │ │ ├── const-agg [type=int, outer=(4)] - │ │ │ │ │ │ └── variable: vcpus [type=int] - │ │ │ │ │ ├── const-agg [type=int, outer=(5)] - │ │ │ │ │ │ └── variable: root_gb [type=int] - │ │ │ │ │ ├── const-agg [type=int, outer=(6)] - │ │ │ │ │ │ └── variable: ephemeral_gb [type=int] - │ │ │ │ │ ├── const-agg [type=string, outer=(7)] - │ │ │ │ │ │ └── variable: flavorid [type=string] - │ │ │ │ │ ├── const-agg [type=int, outer=(8)] - │ │ │ │ │ │ └── variable: swap [type=int] - │ │ │ │ │ ├── const-agg [type=float, outer=(9)] - │ │ │ │ │ │ └── variable: rxtx_factor [type=float] - │ │ │ │ │ ├── const-agg [type=int, outer=(10)] - │ │ │ │ │ │ └── variable: vcpu_weight [type=int] - │ │ │ │ │ ├── const-agg [type=bool, outer=(11)] - │ │ │ │ │ │ └── variable: disabled [type=bool] - │ │ │ │ │ ├── const-agg [type=bool, outer=(12)] - │ │ │ │ │ │ └── variable: is_public [type=bool] - │ │ │ │ │ ├── const-agg [type=bool, outer=(13)] - │ │ │ │ │ │ └── variable: instance_types.deleted [type=bool] - │ │ │ │ │ ├── const-agg [type=timestamp, outer=(14)] - │ │ │ │ │ │ └── variable: instance_types.deleted_at [type=timestamp] - │ │ │ │ │ ├── const-agg [type=timestamp, outer=(15)] - │ │ │ │ │ │ └── variable: instance_types.created_at [type=timestamp] - │ │ │ │ │ └── const-agg [type=timestamp, outer=(16)] - │ │ │ │ │ └── variable: instance_types.updated_at [type=timestamp] - │ │ │ │ └── filters - │ │ │ │ └── (is_public = true) OR (true_agg IS NOT NULL) [type=bool, outer=(12,26)] - │ │ │ └── placeholder: $5 [type=int] - │ │ └── placeholder: $6 [type=int] - │ └── filters - │ └── instance_type_extra_specs_1.deleted = $7 [type=bool, outer=(32), constraints=(/32: (/NULL - ])] - └── filters (true) + │ │ │ │ │ │ │ ├── key: (18-20) + │ │ │ │ │ │ │ ├── ordering: +18 + │ │ │ │ │ │ │ ├── scan instance_type_projects@secondary + │ │ │ │ │ │ │ │ ├── columns: instance_type_projects.instance_type_id:18(int!null) project_id:19(string) instance_type_projects.deleted:20(bool) + │ │ │ │ │ │ │ │ ├── lax-key: (18-20) + │ │ │ │ │ │ │ │ └── ordering: +18 + │ │ │ │ │ │ │ └── filters + │ │ │ │ │ │ │ ├── instance_type_projects.deleted = $2 [type=bool, outer=(20), constraints=(/20: (/NULL - ])] + │ │ │ │ │ │ │ ├── project_id = $3 [type=bool, outer=(19), constraints=(/19: (/NULL - ])] + │ │ │ │ │ │ │ └── instance_type_projects.instance_type_id = $4 [type=bool, outer=(18), constraints=(/18: (/NULL - ])] + │ │ │ │ │ │ └── projections + │ │ │ │ │ │ └── true [type=bool] + │ │ │ │ │ └── filters (true) + │ │ │ │ └── aggregations + │ │ │ │ ├── const-not-null-agg [type=bool, outer=(25)] + │ │ │ │ │ └── variable: true [type=bool] + │ │ │ │ ├── const-agg [type=string, outer=(2)] + │ │ │ │ │ └── variable: name [type=string] + │ │ │ │ ├── const-agg [type=int, outer=(3)] + │ │ │ │ │ └── variable: memory_mb [type=int] + │ │ │ │ ├── const-agg [type=int, outer=(4)] + │ │ │ │ │ └── variable: vcpus [type=int] + │ │ │ │ ├── const-agg [type=int, outer=(5)] + │ │ │ │ │ └── variable: root_gb [type=int] + │ │ │ │ ├── const-agg [type=int, outer=(6)] + │ │ │ │ │ └── variable: ephemeral_gb [type=int] + │ │ │ │ ├── const-agg [type=string, outer=(7)] + │ │ │ │ │ └── variable: flavorid [type=string] + │ │ │ │ ├── const-agg [type=int, outer=(8)] + │ │ │ │ │ └── variable: swap [type=int] + │ │ │ │ ├── const-agg [type=float, outer=(9)] + │ │ │ │ │ └── variable: rxtx_factor [type=float] + │ │ │ │ ├── const-agg [type=int, outer=(10)] + │ │ │ │ │ └── variable: vcpu_weight [type=int] + │ │ │ │ ├── const-agg [type=bool, outer=(11)] + │ │ │ │ │ └── variable: disabled [type=bool] + │ │ │ │ ├── const-agg [type=bool, outer=(12)] + │ │ │ │ │ └── variable: is_public [type=bool] + │ │ │ │ ├── const-agg [type=bool, outer=(13)] + │ │ │ │ │ └── variable: instance_types.deleted [type=bool] + │ │ │ │ ├── const-agg [type=timestamp, outer=(14)] + │ │ │ │ │ └── variable: instance_types.deleted_at [type=timestamp] + │ │ │ │ ├── const-agg [type=timestamp, outer=(15)] + │ │ │ │ │ └── variable: instance_types.created_at [type=timestamp] + │ │ │ │ └── const-agg [type=timestamp, outer=(16)] + │ │ │ │ └── variable: instance_types.updated_at [type=timestamp] + │ │ │ └── filters + │ │ │ └── (is_public = true) OR (true_agg IS NOT NULL) [type=bool, outer=(12,26)] + │ │ └── placeholder: $5 [type=int] + │ └── placeholder: $6 [type=int] + └── filters + └── instance_type_extra_specs_1.instance_type_id = instance_types.id [type=bool, outer=(1,31), constraints=(/1: (/NULL - ]; /31: (/NULL - ]), fd=(1)==(31), (31)==(1)] opt select anon_1.flavors_created_at as anon_1_flavors_created_at, @@ -1997,121 +2003,124 @@ project ├── side-effects, has-placeholder ├── key: (1,28) ├── fd: (1)-->(2-16), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16), (28)-->(29-35), (29,31,32)~~>(28,30,33-35) - └── left-join (lookup instance_type_extra_specs) + └── right-join (hash) ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) instance_type_extra_specs_1.id:28(int) key:29(string) value:30(string) instance_type_extra_specs_1.instance_type_id:31(int) instance_type_extra_specs_1.deleted:32(bool) instance_type_extra_specs_1.deleted_at:33(timestamp) instance_type_extra_specs_1.created_at:34(timestamp) instance_type_extra_specs_1.updated_at:35(timestamp) - ├── key columns: [28] = [28] ├── side-effects, has-placeholder ├── key: (1,28) ├── fd: (1)-->(2-16,26), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16), (28)-->(29-35), (29,31,32)~~>(28,30,33-35) - ├── left-join (lookup instance_type_extra_specs@secondary) - │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) instance_type_extra_specs_1.id:28(int) key:29(string) instance_type_extra_specs_1.instance_type_id:31(int) instance_type_extra_specs_1.deleted:32(bool) - │ ├── key columns: [1] = [31] + ├── select + │ ├── columns: instance_type_extra_specs_1.id:28(int!null) key:29(string) value:30(string) instance_type_extra_specs_1.instance_type_id:31(int!null) instance_type_extra_specs_1.deleted:32(bool!null) instance_type_extra_specs_1.deleted_at:33(timestamp) instance_type_extra_specs_1.created_at:34(timestamp) instance_type_extra_specs_1.updated_at:35(timestamp) + │ ├── has-placeholder + │ ├── key: (28) + │ ├── fd: (28)-->(29-35), (29,31,32)~~>(28,30,33-35) + │ ├── scan instance_type_extra_specs_1 + │ │ ├── columns: instance_type_extra_specs_1.id:28(int!null) key:29(string) value:30(string) instance_type_extra_specs_1.instance_type_id:31(int!null) instance_type_extra_specs_1.deleted:32(bool) instance_type_extra_specs_1.deleted_at:33(timestamp) instance_type_extra_specs_1.created_at:34(timestamp) instance_type_extra_specs_1.updated_at:35(timestamp) + │ │ ├── key: (28) + │ │ └── fd: (28)-->(29-35), (29,31,32)~~>(28,30,33-35) + │ └── filters + │ └── instance_type_extra_specs_1.deleted = $7 [type=bool, outer=(32), constraints=(/32: (/NULL - ])] + ├── limit + │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) │ ├── side-effects, has-placeholder - │ ├── key: (1,28) - │ ├── fd: (1)-->(2-16,26), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16), (28)-->(29,31,32), (29,31,32)~~>(28) - │ ├── limit + │ ├── key: (1) + │ ├── fd: (1)-->(2-16,26), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) + │ ├── offset │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) - │ │ ├── side-effects, has-placeholder + │ │ ├── has-placeholder │ │ ├── key: (1) │ │ ├── fd: (1)-->(2-16,26), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) - │ │ ├── offset + │ │ ├── select │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) │ │ │ ├── has-placeholder │ │ │ ├── key: (1) │ │ │ ├── fd: (1)-->(2-16,26), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) - │ │ │ ├── select + │ │ │ ├── group-by │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) + │ │ │ │ ├── grouping columns: instance_types.id:1(int!null) + │ │ │ │ ├── internal-ordering: +1 │ │ │ │ ├── has-placeholder │ │ │ │ ├── key: (1) │ │ │ │ ├── fd: (1)-->(2-16,26), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) - │ │ │ │ ├── group-by - │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) - │ │ │ │ │ ├── grouping columns: instance_types.id:1(int!null) - │ │ │ │ │ ├── internal-ordering: +1 + │ │ │ │ ├── left-join (merge) + │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int!null) vcpus:4(int!null) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string!null) swap:8(int!null) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool!null) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) instance_type_projects.instance_type_id:18(int) true:25(bool) + │ │ │ │ │ ├── left ordering: +1 + │ │ │ │ │ ├── right ordering: +18 │ │ │ │ │ ├── has-placeholder - │ │ │ │ │ ├── key: (1) - │ │ │ │ │ ├── fd: (1)-->(2-16,26), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) - │ │ │ │ │ ├── left-join (merge) - │ │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int!null) vcpus:4(int!null) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string!null) swap:8(int!null) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool!null) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) instance_type_projects.instance_type_id:18(int) true:25(bool) - │ │ │ │ │ │ ├── left ordering: +1 - │ │ │ │ │ │ ├── right ordering: +18 + │ │ │ │ │ ├── fd: (1)-->(2-16), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16), ()~~>(25) + │ │ │ │ │ ├── ordering: +1 + │ │ │ │ │ ├── select + │ │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int!null) vcpus:4(int!null) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string!null) swap:8(int!null) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool!null) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) │ │ │ │ │ │ ├── has-placeholder - │ │ │ │ │ │ ├── fd: (1)-->(2-16), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16), ()~~>(25) + │ │ │ │ │ │ ├── key: (1) + │ │ │ │ │ │ ├── fd: (1)-->(2-16), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) │ │ │ │ │ │ ├── ordering: +1 + │ │ │ │ │ │ ├── scan instance_types + │ │ │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int!null) vcpus:4(int!null) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int!null) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) + │ │ │ │ │ │ │ ├── key: (1) + │ │ │ │ │ │ │ ├── fd: (1)-->(2-16), (7,13)~~>(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) + │ │ │ │ │ │ │ └── ordering: +1 + │ │ │ │ │ │ └── filters + │ │ │ │ │ │ ├── instance_types.deleted = $1 [type=bool, outer=(13), constraints=(/13: (/NULL - ])] + │ │ │ │ │ │ └── flavorid = $4 [type=bool, outer=(7), constraints=(/7: (/NULL - ])] + │ │ │ │ │ ├── project + │ │ │ │ │ │ ├── columns: true:25(bool!null) instance_type_projects.instance_type_id:18(int!null) + │ │ │ │ │ │ ├── has-placeholder + │ │ │ │ │ │ ├── fd: ()-->(25) + │ │ │ │ │ │ ├── ordering: +18 opt(25) [actual: +18] │ │ │ │ │ │ ├── select - │ │ │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int!null) vcpus:4(int!null) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string!null) swap:8(int!null) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool!null) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) + │ │ │ │ │ │ │ ├── columns: instance_type_projects.instance_type_id:18(int!null) project_id:19(string!null) instance_type_projects.deleted:20(bool!null) │ │ │ │ │ │ │ ├── has-placeholder - │ │ │ │ │ │ │ ├── key: (1) - │ │ │ │ │ │ │ ├── fd: (1)-->(2-16), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) - │ │ │ │ │ │ │ ├── ordering: +1 - │ │ │ │ │ │ │ ├── scan instance_types - │ │ │ │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int!null) vcpus:4(int!null) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int!null) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) - │ │ │ │ │ │ │ │ ├── key: (1) - │ │ │ │ │ │ │ │ ├── fd: (1)-->(2-16), (7,13)~~>(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) - │ │ │ │ │ │ │ │ └── ordering: +1 + │ │ │ │ │ │ │ ├── key: (18-20) + │ │ │ │ │ │ │ ├── ordering: +18 + │ │ │ │ │ │ │ ├── scan instance_type_projects@secondary + │ │ │ │ │ │ │ │ ├── columns: instance_type_projects.instance_type_id:18(int!null) project_id:19(string) instance_type_projects.deleted:20(bool) + │ │ │ │ │ │ │ │ ├── lax-key: (18-20) + │ │ │ │ │ │ │ │ └── ordering: +18 │ │ │ │ │ │ │ └── filters - │ │ │ │ │ │ │ ├── instance_types.deleted = $1 [type=bool, outer=(13), constraints=(/13: (/NULL - ])] - │ │ │ │ │ │ │ └── flavorid = $4 [type=bool, outer=(7), constraints=(/7: (/NULL - ])] - │ │ │ │ │ │ ├── project - │ │ │ │ │ │ │ ├── columns: true:25(bool!null) instance_type_projects.instance_type_id:18(int!null) - │ │ │ │ │ │ │ ├── has-placeholder - │ │ │ │ │ │ │ ├── fd: ()-->(25) - │ │ │ │ │ │ │ ├── ordering: +18 opt(25) [actual: +18] - │ │ │ │ │ │ │ ├── select - │ │ │ │ │ │ │ │ ├── columns: instance_type_projects.instance_type_id:18(int!null) project_id:19(string!null) instance_type_projects.deleted:20(bool!null) - │ │ │ │ │ │ │ │ ├── has-placeholder - │ │ │ │ │ │ │ │ ├── key: (18-20) - │ │ │ │ │ │ │ │ ├── ordering: +18 - │ │ │ │ │ │ │ │ ├── scan instance_type_projects@secondary - │ │ │ │ │ │ │ │ │ ├── columns: instance_type_projects.instance_type_id:18(int!null) project_id:19(string) instance_type_projects.deleted:20(bool) - │ │ │ │ │ │ │ │ │ ├── lax-key: (18-20) - │ │ │ │ │ │ │ │ │ └── ordering: +18 - │ │ │ │ │ │ │ │ └── filters - │ │ │ │ │ │ │ │ ├── instance_type_projects.deleted = $2 [type=bool, outer=(20), constraints=(/20: (/NULL - ])] - │ │ │ │ │ │ │ │ └── project_id = $3 [type=bool, outer=(19), constraints=(/19: (/NULL - ])] - │ │ │ │ │ │ │ └── projections - │ │ │ │ │ │ │ └── true [type=bool] - │ │ │ │ │ │ └── filters (true) - │ │ │ │ │ └── aggregations - │ │ │ │ │ ├── const-not-null-agg [type=bool, outer=(25)] - │ │ │ │ │ │ └── variable: true [type=bool] - │ │ │ │ │ ├── const-agg [type=string, outer=(2)] - │ │ │ │ │ │ └── variable: name [type=string] - │ │ │ │ │ ├── const-agg [type=int, outer=(3)] - │ │ │ │ │ │ └── variable: memory_mb [type=int] - │ │ │ │ │ ├── const-agg [type=int, outer=(4)] - │ │ │ │ │ │ └── variable: vcpus [type=int] - │ │ │ │ │ ├── const-agg [type=int, outer=(5)] - │ │ │ │ │ │ └── variable: root_gb [type=int] - │ │ │ │ │ ├── const-agg [type=int, outer=(6)] - │ │ │ │ │ │ └── variable: ephemeral_gb [type=int] - │ │ │ │ │ ├── const-agg [type=string, outer=(7)] - │ │ │ │ │ │ └── variable: flavorid [type=string] - │ │ │ │ │ ├── const-agg [type=int, outer=(8)] - │ │ │ │ │ │ └── variable: swap [type=int] - │ │ │ │ │ ├── const-agg [type=float, outer=(9)] - │ │ │ │ │ │ └── variable: rxtx_factor [type=float] - │ │ │ │ │ ├── const-agg [type=int, outer=(10)] - │ │ │ │ │ │ └── variable: vcpu_weight [type=int] - │ │ │ │ │ ├── const-agg [type=bool, outer=(11)] - │ │ │ │ │ │ └── variable: disabled [type=bool] - │ │ │ │ │ ├── const-agg [type=bool, outer=(12)] - │ │ │ │ │ │ └── variable: is_public [type=bool] - │ │ │ │ │ ├── const-agg [type=bool, outer=(13)] - │ │ │ │ │ │ └── variable: instance_types.deleted [type=bool] - │ │ │ │ │ ├── const-agg [type=timestamp, outer=(14)] - │ │ │ │ │ │ └── variable: instance_types.deleted_at [type=timestamp] - │ │ │ │ │ ├── const-agg [type=timestamp, outer=(15)] - │ │ │ │ │ │ └── variable: instance_types.created_at [type=timestamp] - │ │ │ │ │ └── const-agg [type=timestamp, outer=(16)] - │ │ │ │ │ └── variable: instance_types.updated_at [type=timestamp] - │ │ │ │ └── filters - │ │ │ │ └── (is_public = true) OR (true_agg IS NOT NULL) [type=bool, outer=(12,26)] - │ │ │ └── placeholder: $5 [type=int] - │ │ └── placeholder: $6 [type=int] - │ └── filters - │ └── instance_type_extra_specs_1.deleted = $7 [type=bool, outer=(32), constraints=(/32: (/NULL - ])] - └── filters (true) + │ │ │ │ │ │ │ ├── instance_type_projects.deleted = $2 [type=bool, outer=(20), constraints=(/20: (/NULL - ])] + │ │ │ │ │ │ │ └── project_id = $3 [type=bool, outer=(19), constraints=(/19: (/NULL - ])] + │ │ │ │ │ │ └── projections + │ │ │ │ │ │ └── true [type=bool] + │ │ │ │ │ └── filters (true) + │ │ │ │ └── aggregations + │ │ │ │ ├── const-not-null-agg [type=bool, outer=(25)] + │ │ │ │ │ └── variable: true [type=bool] + │ │ │ │ ├── const-agg [type=string, outer=(2)] + │ │ │ │ │ └── variable: name [type=string] + │ │ │ │ ├── const-agg [type=int, outer=(3)] + │ │ │ │ │ └── variable: memory_mb [type=int] + │ │ │ │ ├── const-agg [type=int, outer=(4)] + │ │ │ │ │ └── variable: vcpus [type=int] + │ │ │ │ ├── const-agg [type=int, outer=(5)] + │ │ │ │ │ └── variable: root_gb [type=int] + │ │ │ │ ├── const-agg [type=int, outer=(6)] + │ │ │ │ │ └── variable: ephemeral_gb [type=int] + │ │ │ │ ├── const-agg [type=string, outer=(7)] + │ │ │ │ │ └── variable: flavorid [type=string] + │ │ │ │ ├── const-agg [type=int, outer=(8)] + │ │ │ │ │ └── variable: swap [type=int] + │ │ │ │ ├── const-agg [type=float, outer=(9)] + │ │ │ │ │ └── variable: rxtx_factor [type=float] + │ │ │ │ ├── const-agg [type=int, outer=(10)] + │ │ │ │ │ └── variable: vcpu_weight [type=int] + │ │ │ │ ├── const-agg [type=bool, outer=(11)] + │ │ │ │ │ └── variable: disabled [type=bool] + │ │ │ │ ├── const-agg [type=bool, outer=(12)] + │ │ │ │ │ └── variable: is_public [type=bool] + │ │ │ │ ├── const-agg [type=bool, outer=(13)] + │ │ │ │ │ └── variable: instance_types.deleted [type=bool] + │ │ │ │ ├── const-agg [type=timestamp, outer=(14)] + │ │ │ │ │ └── variable: instance_types.deleted_at [type=timestamp] + │ │ │ │ ├── const-agg [type=timestamp, outer=(15)] + │ │ │ │ │ └── variable: instance_types.created_at [type=timestamp] + │ │ │ │ └── const-agg [type=timestamp, outer=(16)] + │ │ │ │ └── variable: instance_types.updated_at [type=timestamp] + │ │ │ └── filters + │ │ │ └── (is_public = true) OR (true_agg IS NOT NULL) [type=bool, outer=(12,26)] + │ │ └── placeholder: $5 [type=int] + │ └── placeholder: $6 [type=int] + └── filters + └── instance_type_extra_specs_1.instance_type_id = instance_types.id [type=bool, outer=(1,31), constraints=(/1: (/NULL - ]; /31: (/NULL - ]), fd=(1)==(31), (31)==(1)] opt select flavors.created_at as flavors_created_at, @@ -2303,139 +2312,144 @@ from (select instance_types.created_at as instance_types_created_at, order by anon_1.instance_types_flavorid asc, anon_1.instance_types_id asc ---- -project +sort ├── columns: anon_1_instance_types_created_at:15(timestamp) anon_1_instance_types_updated_at:16(timestamp) anon_1_instance_types_deleted_at:14(timestamp) anon_1_instance_types_deleted:13(bool) anon_1_instance_types_id:1(int!null) anon_1_instance_types_name:2(string) anon_1_instance_types_memory_mb:3(int) anon_1_instance_types_vcpus:4(int) anon_1_instance_types_root_gb:5(int) anon_1_instance_types_ephemeral_gb:6(int) anon_1_instance_types_flavorid:7(string) anon_1_instance_types_swap:8(int) anon_1_instance_types_rxtx_factor:9(float) anon_1_instance_types_vcpu_weight:10(int) anon_1_instance_types_disabled:11(bool) anon_1_instance_types_is_public:12(bool) instance_type_extra_specs_1_created_at:34(timestamp) instance_type_extra_specs_1_updated_at:35(timestamp) instance_type_extra_specs_1_deleted_at:33(timestamp) instance_type_extra_specs_1_deleted:32(bool) instance_type_extra_specs_1_id:28(int) instance_type_extra_specs_1_key:29(string) instance_type_extra_specs_1_value:30(string) instance_type_extra_specs_1_instance_type_id:31(int) ├── side-effects, has-placeholder ├── key: (1,28) ├── fd: (1)-->(2-16), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16), (28)-->(29-35), (29,31,32)~~>(28,30,33-35) ├── ordering: +7,+1 - └── left-join (lookup instance_type_extra_specs) - ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) instance_type_extra_specs_1.id:28(int) key:29(string) value:30(string) instance_type_extra_specs_1.instance_type_id:31(int) instance_type_extra_specs_1.deleted:32(bool) instance_type_extra_specs_1.deleted_at:33(timestamp) instance_type_extra_specs_1.created_at:34(timestamp) instance_type_extra_specs_1.updated_at:35(timestamp) - ├── key columns: [28] = [28] + └── project + ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) instance_type_extra_specs_1.id:28(int) key:29(string) value:30(string) instance_type_extra_specs_1.instance_type_id:31(int) instance_type_extra_specs_1.deleted:32(bool) instance_type_extra_specs_1.deleted_at:33(timestamp) instance_type_extra_specs_1.created_at:34(timestamp) instance_type_extra_specs_1.updated_at:35(timestamp) ├── side-effects, has-placeholder ├── key: (1,28) - ├── fd: (1)-->(2-16,26), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16), (28)-->(29-35), (29,31,32)~~>(28,30,33-35) - ├── ordering: +7,+1 - ├── left-join (lookup instance_type_extra_specs@secondary) - │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) instance_type_extra_specs_1.id:28(int) key:29(string) instance_type_extra_specs_1.instance_type_id:31(int) instance_type_extra_specs_1.deleted:32(bool) - │ ├── key columns: [1] = [31] - │ ├── side-effects, has-placeholder - │ ├── key: (1,28) - │ ├── fd: (1)-->(2-16,26), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16), (28)-->(29,31,32), (29,31,32)~~>(28) - │ ├── ordering: +7,+1 - │ ├── limit - │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) - │ │ ├── internal-ordering: +7,+1 - │ │ ├── side-effects, has-placeholder - │ │ ├── key: (1) - │ │ ├── fd: (1)-->(2-16,26), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) - │ │ ├── ordering: +7,+1 - │ │ ├── offset - │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) - │ │ │ ├── internal-ordering: +7,+1 - │ │ │ ├── has-placeholder - │ │ │ ├── key: (1) - │ │ │ ├── fd: (1)-->(2-16,26), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) - │ │ │ ├── ordering: +7,+1 - │ │ │ ├── sort - │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) - │ │ │ │ ├── has-placeholder - │ │ │ │ ├── key: (1) - │ │ │ │ ├── fd: (1)-->(2-16,26), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) - │ │ │ │ ├── ordering: +7,+1 - │ │ │ │ └── select - │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) - │ │ │ │ ├── has-placeholder - │ │ │ │ ├── key: (1) - │ │ │ │ ├── fd: (1)-->(2-16,26), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) - │ │ │ │ ├── group-by - │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) - │ │ │ │ │ ├── grouping columns: instance_types.id:1(int!null) - │ │ │ │ │ ├── internal-ordering: +1 - │ │ │ │ │ ├── has-placeholder - │ │ │ │ │ ├── key: (1) - │ │ │ │ │ ├── fd: (1)-->(2-16,26), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) - │ │ │ │ │ ├── left-join (merge) - │ │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int!null) vcpus:4(int!null) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string!null) swap:8(int!null) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool!null) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) instance_type_projects.instance_type_id:18(int) true:25(bool) - │ │ │ │ │ │ ├── left ordering: +1 - │ │ │ │ │ │ ├── right ordering: +18 - │ │ │ │ │ │ ├── has-placeholder - │ │ │ │ │ │ ├── fd: (1)-->(2-16), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16), ()~~>(25) - │ │ │ │ │ │ ├── ordering: +1 - │ │ │ │ │ │ ├── select - │ │ │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int!null) vcpus:4(int!null) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string!null) swap:8(int!null) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool!null) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) - │ │ │ │ │ │ │ ├── has-placeholder - │ │ │ │ │ │ │ ├── key: (1) - │ │ │ │ │ │ │ ├── fd: (1)-->(2-16), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) - │ │ │ │ │ │ │ ├── ordering: +1 - │ │ │ │ │ │ │ ├── scan instance_types - │ │ │ │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int!null) vcpus:4(int!null) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int!null) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) - │ │ │ │ │ │ │ │ ├── key: (1) - │ │ │ │ │ │ │ │ ├── fd: (1)-->(2-16), (7,13)~~>(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) - │ │ │ │ │ │ │ │ └── ordering: +1 - │ │ │ │ │ │ │ └── filters - │ │ │ │ │ │ │ ├── instance_types.deleted = $1 [type=bool, outer=(13), constraints=(/13: (/NULL - ])] - │ │ │ │ │ │ │ └── (flavorid > $4) OR ((flavorid = $5) AND (instance_types.id > $6)) [type=bool, outer=(1,7), constraints=(/7: (/NULL - ])] - │ │ │ │ │ │ ├── project - │ │ │ │ │ │ │ ├── columns: true:25(bool!null) instance_type_projects.instance_type_id:18(int!null) - │ │ │ │ │ │ │ ├── has-placeholder - │ │ │ │ │ │ │ ├── fd: ()-->(25) - │ │ │ │ │ │ │ ├── ordering: +18 opt(25) [actual: +18] - │ │ │ │ │ │ │ ├── select - │ │ │ │ │ │ │ │ ├── columns: instance_type_projects.instance_type_id:18(int!null) project_id:19(string!null) instance_type_projects.deleted:20(bool!null) - │ │ │ │ │ │ │ │ ├── has-placeholder - │ │ │ │ │ │ │ │ ├── key: (18-20) - │ │ │ │ │ │ │ │ ├── ordering: +18 - │ │ │ │ │ │ │ │ ├── scan instance_type_projects@secondary - │ │ │ │ │ │ │ │ │ ├── columns: instance_type_projects.instance_type_id:18(int!null) project_id:19(string) instance_type_projects.deleted:20(bool) - │ │ │ │ │ │ │ │ │ ├── lax-key: (18-20) - │ │ │ │ │ │ │ │ │ └── ordering: +18 - │ │ │ │ │ │ │ │ └── filters - │ │ │ │ │ │ │ │ ├── instance_type_projects.deleted = $2 [type=bool, outer=(20), constraints=(/20: (/NULL - ])] - │ │ │ │ │ │ │ │ └── project_id = $3 [type=bool, outer=(19), constraints=(/19: (/NULL - ])] - │ │ │ │ │ │ │ └── projections - │ │ │ │ │ │ │ └── true [type=bool] - │ │ │ │ │ │ └── filters (true) - │ │ │ │ │ └── aggregations - │ │ │ │ │ ├── const-not-null-agg [type=bool, outer=(25)] - │ │ │ │ │ │ └── variable: true [type=bool] - │ │ │ │ │ ├── const-agg [type=string, outer=(2)] - │ │ │ │ │ │ └── variable: name [type=string] - │ │ │ │ │ ├── const-agg [type=int, outer=(3)] - │ │ │ │ │ │ └── variable: memory_mb [type=int] - │ │ │ │ │ ├── const-agg [type=int, outer=(4)] - │ │ │ │ │ │ └── variable: vcpus [type=int] - │ │ │ │ │ ├── const-agg [type=int, outer=(5)] - │ │ │ │ │ │ └── variable: root_gb [type=int] - │ │ │ │ │ ├── const-agg [type=int, outer=(6)] - │ │ │ │ │ │ └── variable: ephemeral_gb [type=int] - │ │ │ │ │ ├── const-agg [type=string, outer=(7)] - │ │ │ │ │ │ └── variable: flavorid [type=string] - │ │ │ │ │ ├── const-agg [type=int, outer=(8)] - │ │ │ │ │ │ └── variable: swap [type=int] - │ │ │ │ │ ├── const-agg [type=float, outer=(9)] - │ │ │ │ │ │ └── variable: rxtx_factor [type=float] - │ │ │ │ │ ├── const-agg [type=int, outer=(10)] - │ │ │ │ │ │ └── variable: vcpu_weight [type=int] - │ │ │ │ │ ├── const-agg [type=bool, outer=(11)] - │ │ │ │ │ │ └── variable: disabled [type=bool] - │ │ │ │ │ ├── const-agg [type=bool, outer=(12)] - │ │ │ │ │ │ └── variable: is_public [type=bool] - │ │ │ │ │ ├── const-agg [type=bool, outer=(13)] - │ │ │ │ │ │ └── variable: instance_types.deleted [type=bool] - │ │ │ │ │ ├── const-agg [type=timestamp, outer=(14)] - │ │ │ │ │ │ └── variable: instance_types.deleted_at [type=timestamp] - │ │ │ │ │ ├── const-agg [type=timestamp, outer=(15)] - │ │ │ │ │ │ └── variable: instance_types.created_at [type=timestamp] - │ │ │ │ │ └── const-agg [type=timestamp, outer=(16)] - │ │ │ │ │ └── variable: instance_types.updated_at [type=timestamp] - │ │ │ │ └── filters - │ │ │ │ └── (is_public = true) OR (true_agg IS NOT NULL) [type=bool, outer=(12,26)] - │ │ │ └── placeholder: $7 [type=int] - │ │ └── placeholder: $8 [type=int] - │ └── filters - │ └── instance_type_extra_specs_1.deleted = $9 [type=bool, outer=(32), constraints=(/32: (/NULL - ])] - └── filters (true) + ├── fd: (1)-->(2-16), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16), (28)-->(29-35), (29,31,32)~~>(28,30,33-35) + └── right-join (hash) + ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) instance_type_extra_specs_1.id:28(int) key:29(string) value:30(string) instance_type_extra_specs_1.instance_type_id:31(int) instance_type_extra_specs_1.deleted:32(bool) instance_type_extra_specs_1.deleted_at:33(timestamp) instance_type_extra_specs_1.created_at:34(timestamp) instance_type_extra_specs_1.updated_at:35(timestamp) + ├── side-effects, has-placeholder + ├── key: (1,28) + ├── fd: (1)-->(2-16,26), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16), (28)-->(29-35), (29,31,32)~~>(28,30,33-35) + ├── select + │ ├── columns: instance_type_extra_specs_1.id:28(int!null) key:29(string) value:30(string) instance_type_extra_specs_1.instance_type_id:31(int!null) instance_type_extra_specs_1.deleted:32(bool!null) instance_type_extra_specs_1.deleted_at:33(timestamp) instance_type_extra_specs_1.created_at:34(timestamp) instance_type_extra_specs_1.updated_at:35(timestamp) + │ ├── has-placeholder + │ ├── key: (28) + │ ├── fd: (28)-->(29-35), (29,31,32)~~>(28,30,33-35) + │ ├── scan instance_type_extra_specs_1 + │ │ ├── columns: instance_type_extra_specs_1.id:28(int!null) key:29(string) value:30(string) instance_type_extra_specs_1.instance_type_id:31(int!null) instance_type_extra_specs_1.deleted:32(bool) instance_type_extra_specs_1.deleted_at:33(timestamp) instance_type_extra_specs_1.created_at:34(timestamp) instance_type_extra_specs_1.updated_at:35(timestamp) + │ │ ├── key: (28) + │ │ └── fd: (28)-->(29-35), (29,31,32)~~>(28,30,33-35) + │ └── filters + │ └── instance_type_extra_specs_1.deleted = $9 [type=bool, outer=(32), constraints=(/32: (/NULL - ])] + ├── limit + │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) + │ ├── internal-ordering: +7,+1 + │ ├── side-effects, has-placeholder + │ ├── key: (1) + │ ├── fd: (1)-->(2-16,26), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) + │ ├── offset + │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) + │ │ ├── internal-ordering: +7,+1 + │ │ ├── has-placeholder + │ │ ├── key: (1) + │ │ ├── fd: (1)-->(2-16,26), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) + │ │ ├── ordering: +7,+1 + │ │ ├── sort + │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) + │ │ │ ├── has-placeholder + │ │ │ ├── key: (1) + │ │ │ ├── fd: (1)-->(2-16,26), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) + │ │ │ ├── ordering: +7,+1 + │ │ │ └── select + │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) + │ │ │ ├── has-placeholder + │ │ │ ├── key: (1) + │ │ │ ├── fd: (1)-->(2-16,26), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) + │ │ │ ├── group-by + │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) + │ │ │ │ ├── grouping columns: instance_types.id:1(int!null) + │ │ │ │ ├── internal-ordering: +1 + │ │ │ │ ├── has-placeholder + │ │ │ │ ├── key: (1) + │ │ │ │ ├── fd: (1)-->(2-16,26), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) + │ │ │ │ ├── left-join (merge) + │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int!null) vcpus:4(int!null) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string!null) swap:8(int!null) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool!null) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) instance_type_projects.instance_type_id:18(int) true:25(bool) + │ │ │ │ │ ├── left ordering: +1 + │ │ │ │ │ ├── right ordering: +18 + │ │ │ │ │ ├── has-placeholder + │ │ │ │ │ ├── fd: (1)-->(2-16), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16), ()~~>(25) + │ │ │ │ │ ├── ordering: +1 + │ │ │ │ │ ├── select + │ │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int!null) vcpus:4(int!null) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string!null) swap:8(int!null) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool!null) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) + │ │ │ │ │ │ ├── has-placeholder + │ │ │ │ │ │ ├── key: (1) + │ │ │ │ │ │ ├── fd: (1)-->(2-16), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) + │ │ │ │ │ │ ├── ordering: +1 + │ │ │ │ │ │ ├── scan instance_types + │ │ │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int!null) vcpus:4(int!null) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int!null) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) + │ │ │ │ │ │ │ ├── key: (1) + │ │ │ │ │ │ │ ├── fd: (1)-->(2-16), (7,13)~~>(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) + │ │ │ │ │ │ │ └── ordering: +1 + │ │ │ │ │ │ └── filters + │ │ │ │ │ │ ├── instance_types.deleted = $1 [type=bool, outer=(13), constraints=(/13: (/NULL - ])] + │ │ │ │ │ │ └── (flavorid > $4) OR ((flavorid = $5) AND (instance_types.id > $6)) [type=bool, outer=(1,7), constraints=(/7: (/NULL - ])] + │ │ │ │ │ ├── project + │ │ │ │ │ │ ├── columns: true:25(bool!null) instance_type_projects.instance_type_id:18(int!null) + │ │ │ │ │ │ ├── has-placeholder + │ │ │ │ │ │ ├── fd: ()-->(25) + │ │ │ │ │ │ ├── ordering: +18 opt(25) [actual: +18] + │ │ │ │ │ │ ├── select + │ │ │ │ │ │ │ ├── columns: instance_type_projects.instance_type_id:18(int!null) project_id:19(string!null) instance_type_projects.deleted:20(bool!null) + │ │ │ │ │ │ │ ├── has-placeholder + │ │ │ │ │ │ │ ├── key: (18-20) + │ │ │ │ │ │ │ ├── ordering: +18 + │ │ │ │ │ │ │ ├── scan instance_type_projects@secondary + │ │ │ │ │ │ │ │ ├── columns: instance_type_projects.instance_type_id:18(int!null) project_id:19(string) instance_type_projects.deleted:20(bool) + │ │ │ │ │ │ │ │ ├── lax-key: (18-20) + │ │ │ │ │ │ │ │ └── ordering: +18 + │ │ │ │ │ │ │ └── filters + │ │ │ │ │ │ │ ├── instance_type_projects.deleted = $2 [type=bool, outer=(20), constraints=(/20: (/NULL - ])] + │ │ │ │ │ │ │ └── project_id = $3 [type=bool, outer=(19), constraints=(/19: (/NULL - ])] + │ │ │ │ │ │ └── projections + │ │ │ │ │ │ └── true [type=bool] + │ │ │ │ │ └── filters (true) + │ │ │ │ └── aggregations + │ │ │ │ ├── const-not-null-agg [type=bool, outer=(25)] + │ │ │ │ │ └── variable: true [type=bool] + │ │ │ │ ├── const-agg [type=string, outer=(2)] + │ │ │ │ │ └── variable: name [type=string] + │ │ │ │ ├── const-agg [type=int, outer=(3)] + │ │ │ │ │ └── variable: memory_mb [type=int] + │ │ │ │ ├── const-agg [type=int, outer=(4)] + │ │ │ │ │ └── variable: vcpus [type=int] + │ │ │ │ ├── const-agg [type=int, outer=(5)] + │ │ │ │ │ └── variable: root_gb [type=int] + │ │ │ │ ├── const-agg [type=int, outer=(6)] + │ │ │ │ │ └── variable: ephemeral_gb [type=int] + │ │ │ │ ├── const-agg [type=string, outer=(7)] + │ │ │ │ │ └── variable: flavorid [type=string] + │ │ │ │ ├── const-agg [type=int, outer=(8)] + │ │ │ │ │ └── variable: swap [type=int] + │ │ │ │ ├── const-agg [type=float, outer=(9)] + │ │ │ │ │ └── variable: rxtx_factor [type=float] + │ │ │ │ ├── const-agg [type=int, outer=(10)] + │ │ │ │ │ └── variable: vcpu_weight [type=int] + │ │ │ │ ├── const-agg [type=bool, outer=(11)] + │ │ │ │ │ └── variable: disabled [type=bool] + │ │ │ │ ├── const-agg [type=bool, outer=(12)] + │ │ │ │ │ └── variable: is_public [type=bool] + │ │ │ │ ├── const-agg [type=bool, outer=(13)] + │ │ │ │ │ └── variable: instance_types.deleted [type=bool] + │ │ │ │ ├── const-agg [type=timestamp, outer=(14)] + │ │ │ │ │ └── variable: instance_types.deleted_at [type=timestamp] + │ │ │ │ ├── const-agg [type=timestamp, outer=(15)] + │ │ │ │ │ └── variable: instance_types.created_at [type=timestamp] + │ │ │ │ └── const-agg [type=timestamp, outer=(16)] + │ │ │ │ └── variable: instance_types.updated_at [type=timestamp] + │ │ │ └── filters + │ │ │ └── (is_public = true) OR (true_agg IS NOT NULL) [type=bool, outer=(12,26)] + │ │ └── placeholder: $7 [type=int] + │ └── placeholder: $8 [type=int] + └── filters + └── instance_type_extra_specs_1.instance_type_id = instance_types.id [type=bool, outer=(1,31), constraints=(/1: (/NULL - ]; /31: (/NULL - ]), fd=(1)==(31), (31)==(1)] opt select anon_1.flavors_created_at as anon_1_flavors_created_at, @@ -2941,139 +2955,144 @@ from (select instance_types.created_at as instance_types_created_at, order by anon_1.instance_types_deleted asc, anon_1.instance_types_id asc ---- -project +sort ├── columns: anon_1_instance_types_created_at:15(timestamp) anon_1_instance_types_updated_at:16(timestamp) anon_1_instance_types_deleted_at:14(timestamp) anon_1_instance_types_deleted:13(bool) anon_1_instance_types_id:1(int!null) anon_1_instance_types_name:2(string) anon_1_instance_types_memory_mb:3(int) anon_1_instance_types_vcpus:4(int) anon_1_instance_types_root_gb:5(int) anon_1_instance_types_ephemeral_gb:6(int) anon_1_instance_types_flavorid:7(string) anon_1_instance_types_swap:8(int) anon_1_instance_types_rxtx_factor:9(float) anon_1_instance_types_vcpu_weight:10(int) anon_1_instance_types_disabled:11(bool) anon_1_instance_types_is_public:12(bool) instance_type_extra_specs_1_created_at:34(timestamp) instance_type_extra_specs_1_updated_at:35(timestamp) instance_type_extra_specs_1_deleted_at:33(timestamp) instance_type_extra_specs_1_deleted:32(bool) instance_type_extra_specs_1_id:28(int) instance_type_extra_specs_1_key:29(string) instance_type_extra_specs_1_value:30(string) instance_type_extra_specs_1_instance_type_id:31(int) ├── side-effects, has-placeholder ├── key: (1,28) ├── fd: (1)-->(2-16), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16), (28)-->(29-35), (29,31,32)~~>(28,30,33-35) ├── ordering: +13,+1 - └── left-join (lookup instance_type_extra_specs) - ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) instance_type_extra_specs_1.id:28(int) key:29(string) value:30(string) instance_type_extra_specs_1.instance_type_id:31(int) instance_type_extra_specs_1.deleted:32(bool) instance_type_extra_specs_1.deleted_at:33(timestamp) instance_type_extra_specs_1.created_at:34(timestamp) instance_type_extra_specs_1.updated_at:35(timestamp) - ├── key columns: [28] = [28] + └── project + ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) instance_type_extra_specs_1.id:28(int) key:29(string) value:30(string) instance_type_extra_specs_1.instance_type_id:31(int) instance_type_extra_specs_1.deleted:32(bool) instance_type_extra_specs_1.deleted_at:33(timestamp) instance_type_extra_specs_1.created_at:34(timestamp) instance_type_extra_specs_1.updated_at:35(timestamp) ├── side-effects, has-placeholder ├── key: (1,28) - ├── fd: (1)-->(2-16,26), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16), (28)-->(29-35), (29,31,32)~~>(28,30,33-35) - ├── ordering: +13,+1 - ├── left-join (lookup instance_type_extra_specs@secondary) - │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) instance_type_extra_specs_1.id:28(int) key:29(string) instance_type_extra_specs_1.instance_type_id:31(int) instance_type_extra_specs_1.deleted:32(bool) - │ ├── key columns: [1] = [31] - │ ├── side-effects, has-placeholder - │ ├── key: (1,28) - │ ├── fd: (1)-->(2-16,26), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16), (28)-->(29,31,32), (29,31,32)~~>(28) - │ ├── ordering: +13,+1 - │ ├── limit - │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) - │ │ ├── internal-ordering: +13,+1 - │ │ ├── side-effects, has-placeholder - │ │ ├── key: (1) - │ │ ├── fd: (1)-->(2-16,26), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) - │ │ ├── ordering: +13,+1 - │ │ ├── offset - │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) - │ │ │ ├── internal-ordering: +13,+1 - │ │ │ ├── has-placeholder - │ │ │ ├── key: (1) - │ │ │ ├── fd: (1)-->(2-16,26), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) - │ │ │ ├── ordering: +13,+1 - │ │ │ ├── sort - │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) - │ │ │ │ ├── has-placeholder - │ │ │ │ ├── key: (1) - │ │ │ │ ├── fd: (1)-->(2-16,26), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) - │ │ │ │ ├── ordering: +13,+1 - │ │ │ │ └── select - │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) - │ │ │ │ ├── has-placeholder - │ │ │ │ ├── key: (1) - │ │ │ │ ├── fd: (1)-->(2-16,26), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) - │ │ │ │ ├── group-by - │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) - │ │ │ │ │ ├── grouping columns: instance_types.id:1(int!null) - │ │ │ │ │ ├── internal-ordering: +1 - │ │ │ │ │ ├── has-placeholder - │ │ │ │ │ ├── key: (1) - │ │ │ │ │ ├── fd: (1)-->(2-16,26), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) - │ │ │ │ │ ├── left-join (merge) - │ │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int!null) vcpus:4(int!null) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string!null) swap:8(int!null) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool!null) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) instance_type_projects.instance_type_id:18(int) true:25(bool) - │ │ │ │ │ │ ├── left ordering: +1 - │ │ │ │ │ │ ├── right ordering: +18 - │ │ │ │ │ │ ├── has-placeholder - │ │ │ │ │ │ ├── fd: (1)-->(2-16), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16), ()~~>(25) - │ │ │ │ │ │ ├── ordering: +1 - │ │ │ │ │ │ ├── select - │ │ │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int!null) vcpus:4(int!null) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string!null) swap:8(int!null) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool!null) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) - │ │ │ │ │ │ │ ├── has-placeholder - │ │ │ │ │ │ │ ├── key: (1) - │ │ │ │ │ │ │ ├── fd: (1)-->(2-16), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) - │ │ │ │ │ │ │ ├── ordering: +1 - │ │ │ │ │ │ │ ├── scan instance_types - │ │ │ │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int!null) vcpus:4(int!null) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int!null) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) - │ │ │ │ │ │ │ │ ├── key: (1) - │ │ │ │ │ │ │ │ ├── fd: (1)-->(2-16), (7,13)~~>(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) - │ │ │ │ │ │ │ │ └── ordering: +1 - │ │ │ │ │ │ │ └── filters - │ │ │ │ │ │ │ ├── instance_types.deleted = $1 [type=bool, outer=(13), constraints=(/13: (/NULL - ])] - │ │ │ │ │ │ │ └── flavorid = $4 [type=bool, outer=(7), constraints=(/7: (/NULL - ])] - │ │ │ │ │ │ ├── project - │ │ │ │ │ │ │ ├── columns: true:25(bool!null) instance_type_projects.instance_type_id:18(int!null) - │ │ │ │ │ │ │ ├── has-placeholder - │ │ │ │ │ │ │ ├── fd: ()-->(25) - │ │ │ │ │ │ │ ├── ordering: +18 opt(25) [actual: +18] - │ │ │ │ │ │ │ ├── select - │ │ │ │ │ │ │ │ ├── columns: instance_type_projects.instance_type_id:18(int!null) project_id:19(string!null) instance_type_projects.deleted:20(bool!null) - │ │ │ │ │ │ │ │ ├── has-placeholder - │ │ │ │ │ │ │ │ ├── key: (18-20) - │ │ │ │ │ │ │ │ ├── ordering: +18 - │ │ │ │ │ │ │ │ ├── scan instance_type_projects@secondary - │ │ │ │ │ │ │ │ │ ├── columns: instance_type_projects.instance_type_id:18(int!null) project_id:19(string) instance_type_projects.deleted:20(bool) - │ │ │ │ │ │ │ │ │ ├── lax-key: (18-20) - │ │ │ │ │ │ │ │ │ └── ordering: +18 - │ │ │ │ │ │ │ │ └── filters - │ │ │ │ │ │ │ │ ├── instance_type_projects.deleted = $2 [type=bool, outer=(20), constraints=(/20: (/NULL - ])] - │ │ │ │ │ │ │ │ └── project_id = $3 [type=bool, outer=(19), constraints=(/19: (/NULL - ])] - │ │ │ │ │ │ │ └── projections - │ │ │ │ │ │ │ └── true [type=bool] - │ │ │ │ │ │ └── filters (true) - │ │ │ │ │ └── aggregations - │ │ │ │ │ ├── const-not-null-agg [type=bool, outer=(25)] - │ │ │ │ │ │ └── variable: true [type=bool] - │ │ │ │ │ ├── const-agg [type=string, outer=(2)] - │ │ │ │ │ │ └── variable: name [type=string] - │ │ │ │ │ ├── const-agg [type=int, outer=(3)] - │ │ │ │ │ │ └── variable: memory_mb [type=int] - │ │ │ │ │ ├── const-agg [type=int, outer=(4)] - │ │ │ │ │ │ └── variable: vcpus [type=int] - │ │ │ │ │ ├── const-agg [type=int, outer=(5)] - │ │ │ │ │ │ └── variable: root_gb [type=int] - │ │ │ │ │ ├── const-agg [type=int, outer=(6)] - │ │ │ │ │ │ └── variable: ephemeral_gb [type=int] - │ │ │ │ │ ├── const-agg [type=string, outer=(7)] - │ │ │ │ │ │ └── variable: flavorid [type=string] - │ │ │ │ │ ├── const-agg [type=int, outer=(8)] - │ │ │ │ │ │ └── variable: swap [type=int] - │ │ │ │ │ ├── const-agg [type=float, outer=(9)] - │ │ │ │ │ │ └── variable: rxtx_factor [type=float] - │ │ │ │ │ ├── const-agg [type=int, outer=(10)] - │ │ │ │ │ │ └── variable: vcpu_weight [type=int] - │ │ │ │ │ ├── const-agg [type=bool, outer=(11)] - │ │ │ │ │ │ └── variable: disabled [type=bool] - │ │ │ │ │ ├── const-agg [type=bool, outer=(12)] - │ │ │ │ │ │ └── variable: is_public [type=bool] - │ │ │ │ │ ├── const-agg [type=bool, outer=(13)] - │ │ │ │ │ │ └── variable: instance_types.deleted [type=bool] - │ │ │ │ │ ├── const-agg [type=timestamp, outer=(14)] - │ │ │ │ │ │ └── variable: instance_types.deleted_at [type=timestamp] - │ │ │ │ │ ├── const-agg [type=timestamp, outer=(15)] - │ │ │ │ │ │ └── variable: instance_types.created_at [type=timestamp] - │ │ │ │ │ └── const-agg [type=timestamp, outer=(16)] - │ │ │ │ │ └── variable: instance_types.updated_at [type=timestamp] - │ │ │ │ └── filters - │ │ │ │ └── (is_public = true) OR (true_agg IS NOT NULL) [type=bool, outer=(12,26)] - │ │ │ └── placeholder: $5 [type=int] - │ │ └── placeholder: $6 [type=int] - │ └── filters - │ └── instance_type_extra_specs_1.deleted = $7 [type=bool, outer=(32), constraints=(/32: (/NULL - ])] - └── filters (true) + ├── fd: (1)-->(2-16), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16), (28)-->(29-35), (29,31,32)~~>(28,30,33-35) + └── right-join (hash) + ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) instance_type_extra_specs_1.id:28(int) key:29(string) value:30(string) instance_type_extra_specs_1.instance_type_id:31(int) instance_type_extra_specs_1.deleted:32(bool) instance_type_extra_specs_1.deleted_at:33(timestamp) instance_type_extra_specs_1.created_at:34(timestamp) instance_type_extra_specs_1.updated_at:35(timestamp) + ├── side-effects, has-placeholder + ├── key: (1,28) + ├── fd: (1)-->(2-16,26), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16), (28)-->(29-35), (29,31,32)~~>(28,30,33-35) + ├── select + │ ├── columns: instance_type_extra_specs_1.id:28(int!null) key:29(string) value:30(string) instance_type_extra_specs_1.instance_type_id:31(int!null) instance_type_extra_specs_1.deleted:32(bool!null) instance_type_extra_specs_1.deleted_at:33(timestamp) instance_type_extra_specs_1.created_at:34(timestamp) instance_type_extra_specs_1.updated_at:35(timestamp) + │ ├── has-placeholder + │ ├── key: (28) + │ ├── fd: (28)-->(29-35), (29,31,32)~~>(28,30,33-35) + │ ├── scan instance_type_extra_specs_1 + │ │ ├── columns: instance_type_extra_specs_1.id:28(int!null) key:29(string) value:30(string) instance_type_extra_specs_1.instance_type_id:31(int!null) instance_type_extra_specs_1.deleted:32(bool) instance_type_extra_specs_1.deleted_at:33(timestamp) instance_type_extra_specs_1.created_at:34(timestamp) instance_type_extra_specs_1.updated_at:35(timestamp) + │ │ ├── key: (28) + │ │ └── fd: (28)-->(29-35), (29,31,32)~~>(28,30,33-35) + │ └── filters + │ └── instance_type_extra_specs_1.deleted = $7 [type=bool, outer=(32), constraints=(/32: (/NULL - ])] + ├── limit + │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) + │ ├── internal-ordering: +13,+1 + │ ├── side-effects, has-placeholder + │ ├── key: (1) + │ ├── fd: (1)-->(2-16,26), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) + │ ├── offset + │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) + │ │ ├── internal-ordering: +13,+1 + │ │ ├── has-placeholder + │ │ ├── key: (1) + │ │ ├── fd: (1)-->(2-16,26), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) + │ │ ├── ordering: +13,+1 + │ │ ├── sort + │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) + │ │ │ ├── has-placeholder + │ │ │ ├── key: (1) + │ │ │ ├── fd: (1)-->(2-16,26), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) + │ │ │ ├── ordering: +13,+1 + │ │ │ └── select + │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) + │ │ │ ├── has-placeholder + │ │ │ ├── key: (1) + │ │ │ ├── fd: (1)-->(2-16,26), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) + │ │ │ ├── group-by + │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int) vcpus:4(int) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) true_agg:26(bool) + │ │ │ │ ├── grouping columns: instance_types.id:1(int!null) + │ │ │ │ ├── internal-ordering: +1 + │ │ │ │ ├── has-placeholder + │ │ │ │ ├── key: (1) + │ │ │ │ ├── fd: (1)-->(2-16,26), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) + │ │ │ │ ├── left-join (merge) + │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int!null) vcpus:4(int!null) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string!null) swap:8(int!null) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool!null) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) instance_type_projects.instance_type_id:18(int) true:25(bool) + │ │ │ │ │ ├── left ordering: +1 + │ │ │ │ │ ├── right ordering: +18 + │ │ │ │ │ ├── has-placeholder + │ │ │ │ │ ├── fd: (1)-->(2-16), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16), ()~~>(25) + │ │ │ │ │ ├── ordering: +1 + │ │ │ │ │ ├── select + │ │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int!null) vcpus:4(int!null) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string!null) swap:8(int!null) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool!null) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) + │ │ │ │ │ │ ├── has-placeholder + │ │ │ │ │ │ ├── key: (1) + │ │ │ │ │ │ ├── fd: (1)-->(2-16), (7,13)-->(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) + │ │ │ │ │ │ ├── ordering: +1 + │ │ │ │ │ │ ├── scan instance_types + │ │ │ │ │ │ │ ├── columns: instance_types.id:1(int!null) name:2(string) memory_mb:3(int!null) vcpus:4(int!null) root_gb:5(int) ephemeral_gb:6(int) flavorid:7(string) swap:8(int!null) rxtx_factor:9(float) vcpu_weight:10(int) disabled:11(bool) is_public:12(bool) instance_types.deleted:13(bool) instance_types.deleted_at:14(timestamp) instance_types.created_at:15(timestamp) instance_types.updated_at:16(timestamp) + │ │ │ │ │ │ │ ├── key: (1) + │ │ │ │ │ │ │ ├── fd: (1)-->(2-16), (7,13)~~>(1-6,8-12,14-16), (2,13)~~>(1,3-12,14-16) + │ │ │ │ │ │ │ └── ordering: +1 + │ │ │ │ │ │ └── filters + │ │ │ │ │ │ ├── instance_types.deleted = $1 [type=bool, outer=(13), constraints=(/13: (/NULL - ])] + │ │ │ │ │ │ └── flavorid = $4 [type=bool, outer=(7), constraints=(/7: (/NULL - ])] + │ │ │ │ │ ├── project + │ │ │ │ │ │ ├── columns: true:25(bool!null) instance_type_projects.instance_type_id:18(int!null) + │ │ │ │ │ │ ├── has-placeholder + │ │ │ │ │ │ ├── fd: ()-->(25) + │ │ │ │ │ │ ├── ordering: +18 opt(25) [actual: +18] + │ │ │ │ │ │ ├── select + │ │ │ │ │ │ │ ├── columns: instance_type_projects.instance_type_id:18(int!null) project_id:19(string!null) instance_type_projects.deleted:20(bool!null) + │ │ │ │ │ │ │ ├── has-placeholder + │ │ │ │ │ │ │ ├── key: (18-20) + │ │ │ │ │ │ │ ├── ordering: +18 + │ │ │ │ │ │ │ ├── scan instance_type_projects@secondary + │ │ │ │ │ │ │ │ ├── columns: instance_type_projects.instance_type_id:18(int!null) project_id:19(string) instance_type_projects.deleted:20(bool) + │ │ │ │ │ │ │ │ ├── lax-key: (18-20) + │ │ │ │ │ │ │ │ └── ordering: +18 + │ │ │ │ │ │ │ └── filters + │ │ │ │ │ │ │ ├── instance_type_projects.deleted = $2 [type=bool, outer=(20), constraints=(/20: (/NULL - ])] + │ │ │ │ │ │ │ └── project_id = $3 [type=bool, outer=(19), constraints=(/19: (/NULL - ])] + │ │ │ │ │ │ └── projections + │ │ │ │ │ │ └── true [type=bool] + │ │ │ │ │ └── filters (true) + │ │ │ │ └── aggregations + │ │ │ │ ├── const-not-null-agg [type=bool, outer=(25)] + │ │ │ │ │ └── variable: true [type=bool] + │ │ │ │ ├── const-agg [type=string, outer=(2)] + │ │ │ │ │ └── variable: name [type=string] + │ │ │ │ ├── const-agg [type=int, outer=(3)] + │ │ │ │ │ └── variable: memory_mb [type=int] + │ │ │ │ ├── const-agg [type=int, outer=(4)] + │ │ │ │ │ └── variable: vcpus [type=int] + │ │ │ │ ├── const-agg [type=int, outer=(5)] + │ │ │ │ │ └── variable: root_gb [type=int] + │ │ │ │ ├── const-agg [type=int, outer=(6)] + │ │ │ │ │ └── variable: ephemeral_gb [type=int] + │ │ │ │ ├── const-agg [type=string, outer=(7)] + │ │ │ │ │ └── variable: flavorid [type=string] + │ │ │ │ ├── const-agg [type=int, outer=(8)] + │ │ │ │ │ └── variable: swap [type=int] + │ │ │ │ ├── const-agg [type=float, outer=(9)] + │ │ │ │ │ └── variable: rxtx_factor [type=float] + │ │ │ │ ├── const-agg [type=int, outer=(10)] + │ │ │ │ │ └── variable: vcpu_weight [type=int] + │ │ │ │ ├── const-agg [type=bool, outer=(11)] + │ │ │ │ │ └── variable: disabled [type=bool] + │ │ │ │ ├── const-agg [type=bool, outer=(12)] + │ │ │ │ │ └── variable: is_public [type=bool] + │ │ │ │ ├── const-agg [type=bool, outer=(13)] + │ │ │ │ │ └── variable: instance_types.deleted [type=bool] + │ │ │ │ ├── const-agg [type=timestamp, outer=(14)] + │ │ │ │ │ └── variable: instance_types.deleted_at [type=timestamp] + │ │ │ │ ├── const-agg [type=timestamp, outer=(15)] + │ │ │ │ │ └── variable: instance_types.created_at [type=timestamp] + │ │ │ │ └── const-agg [type=timestamp, outer=(16)] + │ │ │ │ └── variable: instance_types.updated_at [type=timestamp] + │ │ │ └── filters + │ │ │ └── (is_public = true) OR (true_agg IS NOT NULL) [type=bool, outer=(12,26)] + │ │ └── placeholder: $5 [type=int] + │ └── placeholder: $6 [type=int] + └── filters + └── instance_type_extra_specs_1.instance_type_id = instance_types.id [type=bool, outer=(1,31), constraints=(/1: (/NULL - ]; /31: (/NULL - ]), fd=(1)==(31), (31)==(1)] opt select anon_1.flavors_created_at as anon_1_flavors_created_at, diff --git a/pkg/sql/opt/xform/testdata/external/tpcc b/pkg/sql/opt/xform/testdata/external/tpcc index 4074741bd2c9..f4c8712dfa8b 100644 --- a/pkg/sql/opt/xform/testdata/external/tpcc +++ b/pkg/sql/opt/xform/testdata/external/tpcc @@ -1597,7 +1597,7 @@ scalar-group-by ├── columns: count:28(int) ├── cardinality: [1 - 1] ├── stats: [rows=1] - ├── cost: 1551.05048 + ├── cost: 1469.11581 ├── key: () ├── fd: ()-->(28) ├── prune: (28) @@ -1605,7 +1605,7 @@ scalar-group-by │ ├── columns: ol_o_id:1(int!null) ol_d_id:2(int!null) ol_w_id:3(int!null) ol_i_id:5(int!null) s_i_id:11(int!null) s_w_id:12(int!null) s_quantity:13(int!null) │ ├── key columns: [3 5] = [12 11] │ ├── stats: [rows=234.432912, distinct(1)=19.9998377, null(1)=0, distinct(2)=1, null(2)=0, distinct(3)=1, null(3)=0, distinct(5)=199.843131, null(5)=0, distinct(11)=199.843131, null(11)=0, distinct(12)=1, null(12)=0, distinct(13)=30.3199861, null(13)=0] - │ ├── cost: 1548.68615 + │ ├── cost: 1466.75148 │ ├── fd: ()-->(2,3,12), (11)-->(13), (5)==(11), (11)==(5), (3)==(12), (12)==(3) │ ├── interesting orderings: (+3,+2,-1) │ ├── scan order_line @@ -1650,7 +1650,7 @@ scalar-group-by ├── columns: count:22(int) ├── cardinality: [1 - 1] ├── stats: [rows=1] - ├── cost: 1264.74667 + ├── cost: 1265.41333 ├── key: () ├── fd: ()-->(22) ├── prune: (22) @@ -1659,7 +1659,7 @@ scalar-group-by │ ├── left ordering: +1 │ ├── right ordering: +11 │ ├── stats: [rows=33.3333333, distinct(1)=33.3333333, null(1)=0, distinct(9)=1, null(9)=0, distinct(11)=33.3333333, null(11)=0, distinct(21)=33.3333333, null(21)=0] - │ ├── cost: 1264.39333 + │ ├── cost: 1265.06 │ ├── key: (11) │ ├── fd: (1)-->(9), (11)-->(21), (1)==(11), (11)==(1) │ ├── scan warehouse diff --git a/pkg/sql/opt/xform/testdata/external/tpcc-later-stats b/pkg/sql/opt/xform/testdata/external/tpcc-later-stats index 8f4042f5e668..f144cc4797a0 100644 --- a/pkg/sql/opt/xform/testdata/external/tpcc-later-stats +++ b/pkg/sql/opt/xform/testdata/external/tpcc-later-stats @@ -1599,7 +1599,7 @@ scalar-group-by ├── columns: count:28(int) ├── cardinality: [1 - 1] ├── stats: [rows=1] - ├── cost: 1534.09466 + ├── cost: 1459.30284 ├── key: () ├── fd: ()-->(28) ├── prune: (28) @@ -1607,7 +1607,7 @@ scalar-group-by │ ├── columns: ol_o_id:1(int!null) ol_d_id:2(int!null) ol_w_id:3(int!null) ol_i_id:5(int!null) s_i_id:11(int!null) s_w_id:12(int!null) s_quantity:13(int!null) │ ├── key columns: [3 5] = [12 11] │ ├── stats: [rows=229.899982, distinct(1)=19.9997964, null(1)=0, distinct(2)=1, null(2)=0, distinct(3)=1, null(3)=0, distinct(5)=198.51294, null(5)=0, distinct(11)=198.51294, null(11)=0, distinct(12)=1, null(12)=0, distinct(13)=30.3178347, null(13)=0] - │ ├── cost: 1531.77566 + │ ├── cost: 1456.98384 │ ├── fd: ()-->(2,3,12), (11)-->(13), (5)==(11), (11)==(5), (3)==(12), (12)==(3) │ ├── interesting orderings: (+3,+2,-1) │ ├── scan order_line @@ -1652,7 +1652,7 @@ scalar-group-by ├── columns: count:22(int) ├── cardinality: [1 - 1] ├── stats: [rows=1] - ├── cost: 126.546667 + ├── cost: 126.613333 ├── key: () ├── fd: ()-->(22) ├── prune: (22) @@ -1661,7 +1661,7 @@ scalar-group-by │ ├── left ordering: +1 │ ├── right ordering: +11 │ ├── stats: [rows=3.33333333, distinct(1)=3.33333333, null(1)=0, distinct(9)=3.33333333, null(9)=0, distinct(11)=3.33333333, null(11)=0, distinct(21)=3.33333333, null(21)=0] - │ ├── cost: 126.493333 + │ ├── cost: 126.56 │ ├── key: (11) │ ├── fd: (1)-->(9), (11)-->(21), (1)==(11), (11)==(1) │ ├── scan warehouse diff --git a/pkg/sql/opt/xform/testdata/external/tpcc-no-stats b/pkg/sql/opt/xform/testdata/external/tpcc-no-stats index abeec60c36c6..42a811ad3d5e 100644 --- a/pkg/sql/opt/xform/testdata/external/tpcc-no-stats +++ b/pkg/sql/opt/xform/testdata/external/tpcc-no-stats @@ -1593,7 +1593,7 @@ scalar-group-by ├── columns: count:28(int) ├── cardinality: [1 - 1] ├── stats: [rows=1] - ├── cost: 0.30998 + ├── cost: 0.27446 ├── key: () ├── fd: ()-->(28) ├── prune: (28) @@ -1601,7 +1601,7 @@ scalar-group-by │ ├── columns: ol_o_id:1(int!null) ol_d_id:2(int!null) ol_w_id:3(int!null) ol_i_id:5(int!null) s_i_id:11(int!null) s_w_id:12(int!null) s_quantity:13(int!null) │ ├── key columns: [3 5] = [12 11] │ ├── stats: [rows=0.066, distinct(1)=0.02, null(1)=0, distinct(2)=0.02, null(2)=0, distinct(3)=0.02, null(3)=0, distinct(5)=0.0199982001, null(5)=0, distinct(11)=0.0199982001, null(11)=0, distinct(12)=0.02, null(12)=0, distinct(13)=0.066, null(13)=0] - │ ├── cost: 0.28932 + │ ├── cost: 0.2538 │ ├── fd: ()-->(2,3,12), (11)-->(13), (5)==(11), (11)==(5), (3)==(12), (12)==(3) │ ├── interesting orderings: (+3,+2,-1) │ ├── scan order_line @@ -1646,7 +1646,7 @@ scalar-group-by ├── columns: count:22(int) ├── cardinality: [1 - 1] ├── stats: [rows=1] - ├── cost: 1621.36 + ├── cost: 1763.4 ├── key: () ├── fd: ()-->(22) ├── prune: (22) @@ -1654,7 +1654,7 @@ scalar-group-by │ ├── columns: w_id:1(int!null) w_ytd:9(decimal!null) d_w_id:11(int!null) sum:21(decimal!null) │ ├── key columns: [11] = [1] │ ├── stats: [rows=33, distinct(1)=33, null(1)=0, distinct(9)=33, null(9)=0, distinct(11)=33, null(11)=0, distinct(21)=33, null(21)=0] - │ ├── cost: 1621.01 + │ ├── cost: 1763.05 │ ├── key: (11) │ ├── fd: (1)-->(9), (11)-->(21), (1)==(11), (11)==(1) │ ├── interesting orderings: (+11) diff --git a/pkg/sql/opt/xform/testdata/rules/join b/pkg/sql/opt/xform/testdata/rules/join index 8f6630a0d031..80f6bdd78cbf 100644 --- a/pkg/sql/opt/xform/testdata/rules/join +++ b/pkg/sql/opt/xform/testdata/rules/join @@ -1789,7 +1789,7 @@ select memo SELECT p,q,r,s FROM pqr WHERE q = 1 AND r = 1 AND s = 'foo' ---- -memo (optimized, ~34KB, required=[presentation: p:1,q:2,r:3,s:4]) +memo (optimized, ~41KB, required=[presentation: p:1,q:2,r:3,s:4]) ├── G1: (select G2 G3) (lookup-join G4 G5 pqr,keyCols=[1],outCols=(1-4)) (zigzag-join G3 pqr@q pqr@s) (zigzag-join G3 pqr@q pqr@rs) (lookup-join G6 G7 pqr,keyCols=[1],outCols=(1-4)) (lookup-join G8 G7 pqr,keyCols=[1],outCols=(1-4)) (lookup-join G9 G7 pqr,keyCols=[1],outCols=(1-4)) (select G10 G11) (select G12 G13) (select G14 G7) (select G15 G7) │ └── [presentation: p:1,q:2,r:3,s:4] │ ├── best: (zigzag-join G3 pqr@q pqr@s) @@ -1983,7 +1983,7 @@ inner-join (lookup t5) memo SELECT a FROM t5 WHERE b @> '{"a":1, "c":2}' ---- -memo (optimized, ~11KB, required=[presentation: a:1]) +memo (optimized, ~13KB, required=[presentation: a:1]) ├── G1: (project G2 G3 a) │ └── [presentation: a:1] │ ├── best: (project G2 G3 a) diff --git a/pkg/sql/opt/xform/testdata/rules/join_order b/pkg/sql/opt/xform/testdata/rules/join_order index 926433587226..7944f748a9be 100644 --- a/pkg/sql/opt/xform/testdata/rules/join_order +++ b/pkg/sql/opt/xform/testdata/rules/join_order @@ -127,7 +127,7 @@ inner-join (lookup bx) memo join-limit=3 SELECT * FROM bx, cy, abc WHERE a = 1 AND abc.b = bx.b AND abc.c = cy.c ---- -memo (optimized, ~25KB, required=[presentation: b:1,x:2,c:3,y:4,a:5,b:6,c:7,d:8]) +memo (optimized, ~30KB, required=[presentation: b:1,x:2,c:3,y:4,a:5,b:6,c:7,d:8]) ├── G1: (inner-join G2 G3 G4) (inner-join G3 G2 G4) (merge-join G2 G3 G5 inner-join,+1,+6) (lookup-join G3 G5 bx,keyCols=[6],outCols=(1-8)) (inner-join G6 G7 G8) (inner-join G9 G10 G11) (inner-join G7 G6 G8) (merge-join G6 G7 G5 inner-join,+3,+7) (inner-join G10 G9 G11) (lookup-join G7 G5 cy,keyCols=[7],outCols=(1-8)) (lookup-join G12 G11 abc,keyCols=[11],outCols=(1-8)) │ └── [presentation: b:1,x:2,c:3,y:4,a:5,b:6,c:7,d:8] │ ├── best: (lookup-join G3 G5 bx,keyCols=[6],outCols=(1-8))