diff --git a/pkg/sql/opt/norm/testdata/rules/combo b/pkg/sql/opt/norm/testdata/rules/combo index fbebb9461f41..8f054629a02e 100644 --- a/pkg/sql/opt/norm/testdata/rules/combo +++ b/pkg/sql/opt/norm/testdata/rules/combo @@ -376,7 +376,7 @@ GenerateMergeJoins + └── filters (true) ================================================================================ GenerateLookupJoins - Cost: 1139.94 + Cost: 1149.84 ================================================================================ project ├── columns: s:4(string) @@ -417,7 +417,7 @@ GenerateLookupJoinsWithFilter (no changes) -------------------------------------------------------------------------------- ================================================================================ Final best expression - Cost: 1139.94 + Cost: 1149.84 ================================================================================ project ├── columns: s:4(string) diff --git a/pkg/sql/opt/optgen/exprgen/testdata/join b/pkg/sql/opt/optgen/exprgen/testdata/join index 94d66d22cac6..1b3f6a2dceef 100644 --- a/pkg/sql/opt/optgen/exprgen/testdata/join +++ b/pkg/sql/opt/optgen/exprgen/testdata/join @@ -66,7 +66,7 @@ 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] - ├── cost: 358393.353 + ├── cost: 691726.687 ├── scan t.public.def │ ├── columns: t.public.def.d:1(int) t.public.def.e:2(int) │ ├── stats: [rows=1000] diff --git a/pkg/sql/opt/xform/coster.go b/pkg/sql/opt/xform/coster.go index ebf5e9722ec1..1130c7a51201 100644 --- a/pkg/sql/opt/xform/coster.go +++ b/pkg/sql/opt/xform/coster.go @@ -102,6 +102,13 @@ const ( seqIOCostFactor = 1 randIOCostFactor = 4 + // TODO(justin): make this more sophisticated. + // lookupJoinRetrieveRowCost is the cost to retrieve a single row during a + // lookup join. + // See https://github.com/cockroachdb/cockroach/pull/35561 for the initial + // justification for this constant. + lookupJoinRetrieveRowCost = 2 * seqIOCostFactor + // latencyCostFactor represents the throughput impact of doing scans on an // index that may be remotely located in a different locality. If latencies // are higher, then overall cluster throughput will suffer somewhat, as there @@ -362,7 +369,8 @@ func (c *coster) computeLookupJoinCost(join *memo.LookupJoinExpr) memo.Cost { // rows (relevant when we expect many resulting rows per lookup) and the CPU // cost of emitting the rows. numLookupCols := join.Cols.Difference(join.Input.Relational().OutputCols).Len() - perRowCost := seqIOCostFactor + c.rowScanCost(join.Table, join.Index, numLookupCols) + perRowCost := lookupJoinRetrieveRowCost + + c.rowScanCost(join.Table, join.Index, numLookupCols) // Add a cost if we have to evaluate an ON condition on every row. The more // leftover conditions, the more expensive it should be. We want to diff --git a/pkg/sql/opt/xform/testdata/coster/join b/pkg/sql/opt/xform/testdata/coster/join index 7e47f37927eb..19fe0fcd1be4 100644 --- a/pkg/sql/opt/xform/testdata/coster/join +++ b/pkg/sql/opt/xform/testdata/coster/join @@ -92,7 +92,7 @@ inner-join (lookup a) ├── flags: no-merge-join;no-hash-join ├── key columns: [1] = [4] ├── stats: [rows=1000, distinct(1)=100, null(1)=0, distinct(4)=100, null(4)=0] - ├── cost: 6090.02 + ├── cost: 7090.02 ├── fd: (1)==(4), (4)==(1) ├── scan b │ ├── columns: x:1(int) @@ -283,7 +283,7 @@ project ├── columns: w:1(string!null) x:2(uuid!null) y:3(uuid!null) z:4(string!null) [hidden: d:8(string!null)] ├── cardinality: [0 - 10] ├── stats: [rows=10] - ├── cost: 122481.301 + ├── cost: 164278.036 ├── key: (8) ├── fd: ()-->(1,2), (3)-->(4,8), (8)-->(3,4) ├── ordering: +8 opt(1,2) [actual: +8] @@ -292,22 +292,23 @@ project ├── internal-ordering: +8 opt(1,2,5,6) ├── cardinality: [0 - 10] ├── stats: [rows=10] - ├── cost: 122481.191 + ├── cost: 164277.926 ├── key: (7) ├── fd: ()-->(1,2,5,6), (3)-->(4), (7)-->(8), (8)-->(7), (1)==(5), (5)==(1), (2)==(6), (6)==(2), (3)==(7), (7)==(3) ├── ordering: +8 opt(1,2,5,6) [actual: +8] ├── sort │ ├── columns: w:1(string!null) x:2(uuid!null) y:3(uuid!null) z:4(string!null) a:5(string!null) b:6(uuid!null) c:7(uuid!null) d:8(string!null) │ ├── stats: [rows=50048.8759, distinct(1)=1, null(1)=0, distinct(2)=1, null(2)=0, distinct(3)=2500, null(3)=0, distinct(4)=1000, null(4)=0, distinct(5)=1, null(5)=0, distinct(6)=1, null(6)=0, distinct(7)=2500, null(7)=0, distinct(8)=38781.1698, null(8)=0] - │ ├── cost: 122481.081 + │ ├── cost: 164277.816 │ ├── key: (7) │ ├── fd: ()-->(1,2,5,6), (3)-->(4), (7)-->(8), (8)-->(7), (1)==(5), (5)==(1), (2)==(6), (6)==(2), (3)==(7), (7)==(3) │ ├── ordering: +8 opt(1,2,5,6) [actual: +8] - │ └── inner-join (lookup abcde@idx_abcd) + │ └── inner-join (merge) │ ├── columns: w:1(string!null) x:2(uuid!null) y:3(uuid!null) z:4(string!null) a:5(string!null) b:6(uuid!null) c:7(uuid!null) d:8(string!null) - │ ├── key columns: [1 2 3] = [5 6 7] + │ ├── left ordering: +1,+2,+3 + │ ├── right ordering: +5,+6,+7 │ ├── stats: [rows=50048.8759, distinct(1)=1, null(1)=0, distinct(2)=1, null(2)=0, distinct(3)=2500, null(3)=0, distinct(4)=1000, null(4)=0, distinct(5)=1, null(5)=0, distinct(6)=1, null(6)=0, distinct(7)=2500, null(7)=0, distinct(8)=38781.1698, null(8)=0] - │ ├── cost: 105853.783 + │ ├── cost: 147650.519 │ ├── key: (7) │ ├── fd: ()-->(1,2,5,6), (3)-->(4), (7)-->(8), (8)-->(7), (1)==(5), (5)==(1), (2)==(6), (6)==(2), (3)==(7), (7)==(3) │ ├── scan wxyz @@ -316,8 +317,15 @@ project │ │ ├── stats: [rows=10000, distinct(1)=1, null(1)=0, distinct(2)=1, null(2)=0, distinct(3)=2500, null(3)=0, distinct(4)=1000, null(4)=0] │ │ ├── cost: 10800.01 │ │ ├── key: (3) - │ │ └── fd: ()-->(1,2), (3)-->(4) - │ └── filters - │ ├── a = 'foo' [type=bool, outer=(5), constraints=(/5: [/'foo' - /'foo']; tight), fd=()-->(5)] - │ └── b = '2ab23800-06b1-4e19-a3bb-df3768b808d2' [type=bool, outer=(6), constraints=(/6: [/'2ab23800-06b1-4e19-a3bb-df3768b808d2' - /'2ab23800-06b1-4e19-a3bb-df3768b808d2']; tight), fd=()-->(6)] + │ │ ├── fd: ()-->(1,2), (3)-->(4) + │ │ └── ordering: +3 opt(1,2) [actual: +3] + │ ├── scan abcde@idx_abcd + │ │ ├── columns: a:5(string!null) b:6(uuid!null) c:7(uuid!null) d:8(string!null) + │ │ ├── constraint: /5/6/7/8: [/'foo'/'2ab23800-06b1-4e19-a3bb-df3768b808d2' - /'foo'/'2ab23800-06b1-4e19-a3bb-df3768b808d2'] + │ │ ├── stats: [rows=125000, distinct(5)=1, null(5)=0, distinct(6)=1, null(6)=0, distinct(7)=24975.5859, null(7)=0, distinct(8)=93750, null(8)=0] + │ │ ├── cost: 135000.01 + │ │ ├── key: (7) + │ │ ├── fd: ()-->(5,6), (7)-->(8), (8)-->(7) + │ │ └── ordering: +7 opt(5,6) [actual: +7] + │ └── filters (true) └── const: 10 [type=int] diff --git a/pkg/sql/opt/xform/testdata/coster/zone b/pkg/sql/opt/xform/testdata/coster/zone index 3eb9e44ce7bc..6e7a528c7d6d 100644 --- a/pkg/sql/opt/xform/testdata/coster/zone +++ b/pkg/sql/opt/xform/testdata/coster/zone @@ -317,7 +317,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: 153.0245 + ├── cost: 251.0345 ├── key: (1,4) ├── fd: ()-->(2,5), (1)-->(3), (2,3)~~>(1), (2)==(5), (5)==(2) ├── prune: (1,3,4) @@ -359,7 +359,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: 153.0245 + ├── cost: 251.0345 ├── 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/liquibase b/pkg/sql/opt/xform/testdata/external/liquibase index a8bec4248dfe..24c62f9cacb6 100644 --- a/pkg/sql/opt/xform/testdata/external/liquibase +++ b/pkg/sql/opt/xform/testdata/external/liquibase @@ -301,10 +301,13 @@ project │ │ │ │ ├── columns: c.oid:1(oid!null) c.relname:2(string!null) c.relnamespace:3(oid!null) c.relowner:5(oid!null) c.reltablespace:8(oid!null) c.reltuples:10(float!null) c.relhasindex:13(bool!null) c.relpersistence:15(string!null) c.relkind:17(string!null) c.relhasoids:20(bool!null) c.relhasrules:22(bool!null) c.relhastriggers:23(bool!null) c.relacl:26(string[]) c.reloptions:27(string[]) n.oid:28(oid!null) n.nspname:29(string!null) t.oid:32(oid) spcname:33(string) i.inhrelid:38(oid) i.inhparent:39(oid) c2.oid:41(oid) c2.relname:42(string) c2.relnamespace:43(oid) n2.oid:68(oid) n2.nspname:69(string) indexrelid:72(oid) indrelid:73(oid) indisclustered:79(bool) ci.oid:91(oid) ci.relname:92(string) ftrelid:118(oid) ftserver:119(oid) ftoptions:120(string[]) │ │ │ │ ├── key columns: [1] = [118] │ │ │ │ ├── fd: ()-->(3,28,29), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (3)==(28), (28)==(3), (32)-->(33), (33)-->(32), (41)-->(42,43), (42,43)-->(41), (39)==(41), (41)==(39), (68)~~>(69), (69)~~>(68), (72)-->(73), ()~~>(79), (91)-->(92), (118)-->(119,120) - │ │ │ │ ├── left-join (lookup pg_class) + │ │ │ │ ├── right-join │ │ │ │ │ ├── columns: c.oid:1(oid!null) c.relname:2(string!null) c.relnamespace:3(oid!null) c.relowner:5(oid!null) c.reltablespace:8(oid!null) c.reltuples:10(float!null) c.relhasindex:13(bool!null) c.relpersistence:15(string!null) c.relkind:17(string!null) c.relhasoids:20(bool!null) c.relhasrules:22(bool!null) c.relhastriggers:23(bool!null) c.relacl:26(string[]) c.reloptions:27(string[]) n.oid:28(oid!null) n.nspname:29(string!null) t.oid:32(oid) spcname:33(string) i.inhrelid:38(oid) i.inhparent:39(oid) c2.oid:41(oid) c2.relname:42(string) c2.relnamespace:43(oid) n2.oid:68(oid) n2.nspname:69(string) indexrelid:72(oid) indrelid:73(oid) indisclustered:79(bool) ci.oid:91(oid) ci.relname:92(string) - │ │ │ │ │ ├── key columns: [72] = [91] │ │ │ │ │ ├── fd: ()-->(3,28,29), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (3)==(28), (28)==(3), (32)-->(33), (33)-->(32), (41)-->(42,43), (42,43)-->(41), (39)==(41), (41)==(39), (68)~~>(69), (69)~~>(68), (72)-->(73), ()~~>(79), (91)-->(92) + │ │ │ │ │ ├── scan ci@pg_class_relname_nsp_index + │ │ │ │ │ │ ├── columns: i.inhrelid:38(oid) i.inhparent:39(oid) c2.oid:41(oid) c2.relname:42(string) c2.relnamespace:43(oid) n2.oid:68(oid) n2.nspname:69(string) indexrelid:72(oid) indrelid:73(oid) indisclustered:79(bool) ci.oid:91(oid!null) ci.relname:92(string!null) + │ │ │ │ │ │ ├── key: (91) + │ │ │ │ │ │ └── fd: (91)-->(92) │ │ │ │ │ ├── right-join │ │ │ │ │ │ ├── columns: c.oid:1(oid!null) c.relname:2(string!null) c.relnamespace:3(oid!null) c.relowner:5(oid!null) c.reltablespace:8(oid!null) c.reltuples:10(float!null) c.relhasindex:13(bool!null) c.relpersistence:15(string!null) c.relkind:17(string!null) c.relhasoids:20(bool!null) c.relhasrules:22(bool!null) c.relhastriggers:23(bool!null) c.relacl:26(string[]) c.reloptions:27(string[]) n.oid:28(oid!null) n.nspname:29(string!null) t.oid:32(oid) spcname:33(string) i.inhrelid:38(oid) i.inhparent:39(oid) c2.oid:41(oid) c2.relname:42(string) c2.relnamespace:43(oid) n2.oid:68(oid) n2.nspname:69(string) indexrelid:72(oid) indrelid:73(oid) indisclustered:79(bool) │ │ │ │ │ │ ├── fd: ()-->(3,28,29), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (3)==(28), (28)==(3), (32)-->(33), (33)-->(32), (41)-->(42,43), (42,43)-->(41), (39)==(41), (41)==(39), (68)~~>(69), (69)~~>(68), (72)-->(73), ()~~>(79) @@ -373,7 +376,8 @@ project │ │ │ │ │ │ │ └── i.inhrelid = c.oid [type=bool, outer=(1,38), constraints=(/1: (/NULL - ]; /38: (/NULL - ]), fd=(1)==(38), (38)==(1)] │ │ │ │ │ │ └── filters │ │ │ │ │ │ └── indrelid = c.oid [type=bool, outer=(1,73), constraints=(/1: (/NULL - ]; /73: (/NULL - ]), fd=(1)==(73), (73)==(1)] - │ │ │ │ │ └── filters (true) + │ │ │ │ │ └── filters + │ │ │ │ │ └── ci.oid = indexrelid [type=bool, outer=(72,91), constraints=(/72: (/NULL - ]; /91: (/NULL - ]), fd=(72)==(91), (91)==(72)] │ │ │ │ └── filters (true) │ │ │ └── filters (true) │ │ └── filters diff --git a/pkg/sql/opt/xform/testdata/external/navicat b/pkg/sql/opt/xform/testdata/external/navicat index bb44ea0e95a4..acaeec682822 100644 --- a/pkg/sql/opt/xform/testdata/external/navicat +++ b/pkg/sql/opt/xform/testdata/external/navicat @@ -304,10 +304,13 @@ sort │ │ │ │ ├── columns: c.oid:1(oid!null) c.relname:2(string!null) c.relnamespace:3(oid!null) c.relowner:5(oid!null) c.reltablespace:8(oid!null) c.reltuples:10(float!null) c.relhasindex:13(bool!null) c.relpersistence:15(string!null) c.relkind:17(string!null) c.relhasoids:20(bool!null) c.relhasrules:22(bool!null) c.relhastriggers:23(bool!null) c.relacl:26(string[]) c.reloptions:27(string[]) n.oid:28(oid!null) n.nspname:29(string!null) t.oid:32(oid) spcname:33(string) i.inhrelid:38(oid) i.inhparent:39(oid) c2.oid:41(oid) c2.relname:42(string) c2.relnamespace:43(oid) n2.oid:68(oid) n2.nspname:69(string) indexrelid:72(oid) indrelid:73(oid) indisclustered:79(bool) ci.oid:91(oid) ci.relname:92(string) ftrelid:118(oid) ftserver:119(oid) ftoptions:120(string[]) │ │ │ │ ├── key columns: [1] = [118] │ │ │ │ ├── fd: ()-->(3,28,29), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (3)==(28), (28)==(3), (32)-->(33), (33)-->(32), (41)-->(42,43), (42,43)-->(41), (39)==(41), (41)==(39), (68)~~>(69), (69)~~>(68), (72)-->(73), ()~~>(79), (91)-->(92), (118)-->(119,120) - │ │ │ │ ├── left-join (lookup pg_class) + │ │ │ │ ├── right-join │ │ │ │ │ ├── columns: c.oid:1(oid!null) c.relname:2(string!null) c.relnamespace:3(oid!null) c.relowner:5(oid!null) c.reltablespace:8(oid!null) c.reltuples:10(float!null) c.relhasindex:13(bool!null) c.relpersistence:15(string!null) c.relkind:17(string!null) c.relhasoids:20(bool!null) c.relhasrules:22(bool!null) c.relhastriggers:23(bool!null) c.relacl:26(string[]) c.reloptions:27(string[]) n.oid:28(oid!null) n.nspname:29(string!null) t.oid:32(oid) spcname:33(string) i.inhrelid:38(oid) i.inhparent:39(oid) c2.oid:41(oid) c2.relname:42(string) c2.relnamespace:43(oid) n2.oid:68(oid) n2.nspname:69(string) indexrelid:72(oid) indrelid:73(oid) indisclustered:79(bool) ci.oid:91(oid) ci.relname:92(string) - │ │ │ │ │ ├── key columns: [72] = [91] │ │ │ │ │ ├── fd: ()-->(3,28,29), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (3)==(28), (28)==(3), (32)-->(33), (33)-->(32), (41)-->(42,43), (42,43)-->(41), (39)==(41), (41)==(39), (68)~~>(69), (69)~~>(68), (72)-->(73), ()~~>(79), (91)-->(92) + │ │ │ │ │ ├── scan ci@pg_class_relname_nsp_index + │ │ │ │ │ │ ├── columns: i.inhrelid:38(oid) i.inhparent:39(oid) c2.oid:41(oid) c2.relname:42(string) c2.relnamespace:43(oid) n2.oid:68(oid) n2.nspname:69(string) indexrelid:72(oid) indrelid:73(oid) indisclustered:79(bool) ci.oid:91(oid!null) ci.relname:92(string!null) + │ │ │ │ │ │ ├── key: (91) + │ │ │ │ │ │ └── fd: (91)-->(92) │ │ │ │ │ ├── right-join │ │ │ │ │ │ ├── columns: c.oid:1(oid!null) c.relname:2(string!null) c.relnamespace:3(oid!null) c.relowner:5(oid!null) c.reltablespace:8(oid!null) c.reltuples:10(float!null) c.relhasindex:13(bool!null) c.relpersistence:15(string!null) c.relkind:17(string!null) c.relhasoids:20(bool!null) c.relhasrules:22(bool!null) c.relhastriggers:23(bool!null) c.relacl:26(string[]) c.reloptions:27(string[]) n.oid:28(oid!null) n.nspname:29(string!null) t.oid:32(oid) spcname:33(string) i.inhrelid:38(oid) i.inhparent:39(oid) c2.oid:41(oid) c2.relname:42(string) c2.relnamespace:43(oid) n2.oid:68(oid) n2.nspname:69(string) indexrelid:72(oid) indrelid:73(oid) indisclustered:79(bool) │ │ │ │ │ │ ├── fd: ()-->(3,28,29), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (3)==(28), (28)==(3), (32)-->(33), (33)-->(32), (41)-->(42,43), (42,43)-->(41), (39)==(41), (41)==(39), (68)~~>(69), (69)~~>(68), (72)-->(73), ()~~>(79) @@ -376,7 +379,8 @@ sort │ │ │ │ │ │ │ └── i.inhrelid = c.oid [type=bool, outer=(1,38), constraints=(/1: (/NULL - ]; /38: (/NULL - ]), fd=(1)==(38), (38)==(1)] │ │ │ │ │ │ └── filters │ │ │ │ │ │ └── indrelid = c.oid [type=bool, outer=(1,73), constraints=(/1: (/NULL - ]; /73: (/NULL - ]), fd=(1)==(73), (73)==(1)] - │ │ │ │ │ └── filters (true) + │ │ │ │ │ └── filters + │ │ │ │ │ └── ci.oid = indexrelid [type=bool, outer=(72,91), constraints=(/72: (/NULL - ]; /91: (/NULL - ]), fd=(72)==(91), (91)==(72)] │ │ │ │ └── filters (true) │ │ │ └── filters (true) │ │ └── filters diff --git a/pkg/sql/opt/xform/testdata/external/tpcc b/pkg/sql/opt/xform/testdata/external/tpcc index a58eb257b0ed..7567b7fdac15 100644 --- a/pkg/sql/opt/xform/testdata/external/tpcc +++ b/pkg/sql/opt/xform/testdata/external/tpcc @@ -904,7 +904,7 @@ scalar-group-by ├── columns: count:28(int) ├── cardinality: [1 - 1] ├── stats: [rows=1] - ├── cost: 1.84111111 + ├── cost: 2.84111111 ├── key: () ├── fd: ()-->(28) ├── prune: (28) @@ -912,7 +912,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=1, distinct(1)=0.11109736, null(1)=0, distinct(2)=0.111097416, null(2)=0, distinct(3)=0.111111111, null(3)=0, distinct(5)=0.111111056, null(5)=0, distinct(11)=0.111111056, null(11)=0, distinct(12)=0.111111111, null(12)=0, distinct(13)=1, null(13)=0] - │ ├── cost: 1.81111111 + │ ├── cost: 2.81111111 │ ├── fd: ()-->(2,3,12), (11)-->(13), (5)==(11), (11)==(5), (3)==(12), (12)==(3) │ ├── interesting orderings: (+3,+2,-1) │ ├── scan order_line diff --git a/pkg/sql/opt/xform/testdata/external/tpcc-no-stats b/pkg/sql/opt/xform/testdata/external/tpcc-no-stats index e9a6331c7d78..ca5da68ea602 100644 --- a/pkg/sql/opt/xform/testdata/external/tpcc-no-stats +++ b/pkg/sql/opt/xform/testdata/external/tpcc-no-stats @@ -709,7 +709,7 @@ scalar-group-by ├── columns: count:28(int) ├── cardinality: [1 - 1] ├── stats: [rows=1] - ├── cost: 0.142211111 + ├── cost: 0.178877778 ├── key: () ├── fd: ()-->(28) ├── prune: (28) @@ -717,7 +717,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.0366666667, distinct(1)=0.0111105556, null(1)=0, distinct(2)=0.0111111111, null(2)=0, distinct(3)=0.0111111111, null(3)=0, distinct(5)=0.0111105556, null(5)=0, distinct(11)=0.0111105556, null(11)=0, distinct(12)=0.0111111111, null(12)=0, distinct(13)=0.0366666667, null(13)=0] - │ ├── cost: 0.121844444 + │ ├── cost: 0.158511111 │ ├── fd: ()-->(2,3,12), (11)-->(13), (5)==(11), (11)==(5), (3)==(12), (12)==(3) │ ├── interesting orderings: (+3,+2,-1) │ ├── scan order_line @@ -762,7 +762,7 @@ scalar-group-by ├── columns: count:22(int) ├── cardinality: [1 - 1] ├── stats: [rows=1] - ├── cost: 1588.34 + ├── cost: 1621.34 ├── key: () ├── fd: ()-->(22) ├── prune: (22) @@ -770,7 +770,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)=28.3508504, null(9)=0, distinct(11)=33, null(11)=0, distinct(21)=28.3508504, null(21)=0] - │ ├── cost: 1587.99 + │ ├── cost: 1620.99 │ ├── key: (11) │ ├── fd: (1)-->(9), (11)-->(21), (1)==(11), (11)==(1) │ ├── interesting orderings: (+11) diff --git a/pkg/sql/opt/xform/testdata/external/tpch b/pkg/sql/opt/xform/testdata/external/tpch index f32cfa915300..4cfe4e1b17a2 100644 --- a/pkg/sql/opt/xform/testdata/external/tpch +++ b/pkg/sql/opt/xform/testdata/external/tpch @@ -613,35 +613,46 @@ project │ │ │ │ │ ├── columns: ps_partkey:29(int!null) ps_suppkey:30(int!null) ps_supplycost:32(float!null) │ │ │ │ │ ├── key: (29,30) │ │ │ │ │ └── fd: (29,30)-->(32) - │ │ │ │ ├── inner-join (lookup supplier@s_nk) + │ │ │ │ ├── inner-join (merge) │ │ │ │ │ ├── columns: s_suppkey:34(int!null) s_nationkey:37(int!null) n_nationkey:41(int!null) n_regionkey:43(int!null) r_regionkey:45(int!null) r_name:46(string!null) - │ │ │ │ │ ├── key columns: [41] = [37] + │ │ │ │ │ ├── left ordering: +37 + │ │ │ │ │ ├── right ordering: +41 │ │ │ │ │ ├── key: (34) │ │ │ │ │ ├── fd: ()-->(46), (34)-->(37), (41)-->(43), (43)==(45), (45)==(43), (37)==(41), (41)==(37) - │ │ │ │ │ ├── inner-join (merge) + │ │ │ │ │ ├── scan supplier@s_nk + │ │ │ │ │ │ ├── columns: s_suppkey:34(int!null) s_nationkey:37(int!null) + │ │ │ │ │ │ ├── key: (34) + │ │ │ │ │ │ ├── fd: (34)-->(37) + │ │ │ │ │ │ └── ordering: +37 + │ │ │ │ │ ├── sort │ │ │ │ │ │ ├── columns: n_nationkey:41(int!null) n_regionkey:43(int!null) r_regionkey:45(int!null) r_name:46(string!null) - │ │ │ │ │ │ ├── left ordering: +43 - │ │ │ │ │ │ ├── right ordering: +45 │ │ │ │ │ │ ├── key: (41) │ │ │ │ │ │ ├── fd: ()-->(46), (41)-->(43), (43)==(45), (45)==(43) - │ │ │ │ │ │ ├── scan nation@n_rk - │ │ │ │ │ │ │ ├── columns: n_nationkey:41(int!null) n_regionkey:43(int!null) - │ │ │ │ │ │ │ ├── key: (41) - │ │ │ │ │ │ │ ├── fd: (41)-->(43) - │ │ │ │ │ │ │ └── ordering: +43 - │ │ │ │ │ │ ├── select - │ │ │ │ │ │ │ ├── columns: r_regionkey:45(int!null) r_name:46(string!null) - │ │ │ │ │ │ │ ├── key: (45) - │ │ │ │ │ │ │ ├── fd: ()-->(46) - │ │ │ │ │ │ │ ├── ordering: +45 opt(46) [actual: +45] - │ │ │ │ │ │ │ ├── scan region - │ │ │ │ │ │ │ │ ├── columns: r_regionkey:45(int!null) r_name:46(string!null) - │ │ │ │ │ │ │ │ ├── key: (45) - │ │ │ │ │ │ │ │ ├── fd: (45)-->(46) - │ │ │ │ │ │ │ │ └── ordering: +45 opt(46) [actual: +45] - │ │ │ │ │ │ │ └── filters - │ │ │ │ │ │ │ └── r_name = 'EUROPE' [type=bool, outer=(46), constraints=(/46: [/'EUROPE' - /'EUROPE']; tight), fd=()-->(46)] - │ │ │ │ │ │ └── filters (true) + │ │ │ │ │ │ ├── ordering: +41 opt(46) [actual: +41] + │ │ │ │ │ │ └── inner-join (merge) + │ │ │ │ │ │ ├── columns: n_nationkey:41(int!null) n_regionkey:43(int!null) r_regionkey:45(int!null) r_name:46(string!null) + │ │ │ │ │ │ ├── left ordering: +43 + │ │ │ │ │ │ ├── right ordering: +45 + │ │ │ │ │ │ ├── key: (41) + │ │ │ │ │ │ ├── fd: ()-->(46), (41)-->(43), (43)==(45), (45)==(43) + │ │ │ │ │ │ ├── scan nation@n_rk + │ │ │ │ │ │ │ ├── columns: n_nationkey:41(int!null) n_regionkey:43(int!null) + │ │ │ │ │ │ │ ├── key: (41) + │ │ │ │ │ │ │ ├── fd: (41)-->(43) + │ │ │ │ │ │ │ └── ordering: +43 + │ │ │ │ │ │ ├── select + │ │ │ │ │ │ │ ├── columns: r_regionkey:45(int!null) r_name:46(string!null) + │ │ │ │ │ │ │ ├── key: (45) + │ │ │ │ │ │ │ ├── fd: ()-->(46) + │ │ │ │ │ │ │ ├── ordering: +45 opt(46) [actual: +45] + │ │ │ │ │ │ │ ├── scan region + │ │ │ │ │ │ │ │ ├── columns: r_regionkey:45(int!null) r_name:46(string!null) + │ │ │ │ │ │ │ │ ├── key: (45) + │ │ │ │ │ │ │ │ ├── fd: (45)-->(46) + │ │ │ │ │ │ │ │ └── ordering: +45 opt(46) [actual: +45] + │ │ │ │ │ │ │ └── filters + │ │ │ │ │ │ │ └── r_name = 'EUROPE' [type=bool, outer=(46), constraints=(/46: [/'EUROPE' - /'EUROPE']; tight), fd=()-->(46)] + │ │ │ │ │ │ └── filters (true) │ │ │ │ │ └── filters (true) │ │ │ │ └── filters │ │ │ │ └── s_suppkey = ps_suppkey [type=bool, outer=(30,34), constraints=(/30: (/NULL - ]; /34: (/NULL - ]), fd=(30)==(34), (34)==(30)] @@ -961,31 +972,42 @@ sort │ │ │ │ ├── fd: ()-->(46), (34)-->(37), (41)-->(42,43), (43)==(45), (45)==(43), (37)==(41), (41)==(37), (20)==(34), (34)==(20) │ │ │ │ ├── scan lineitem │ │ │ │ │ └── columns: l_orderkey:18(int!null) l_suppkey:20(int!null) l_extendedprice:23(float!null) l_discount:24(float!null) - │ │ │ │ ├── inner-join (lookup supplier@s_nk) + │ │ │ │ ├── inner-join (merge) │ │ │ │ │ ├── columns: s_suppkey:34(int!null) s_nationkey:37(int!null) n_nationkey:41(int!null) n_name:42(string!null) n_regionkey:43(int!null) r_regionkey:45(int!null) r_name:46(string!null) - │ │ │ │ │ ├── key columns: [41] = [37] + │ │ │ │ │ ├── left ordering: +37 + │ │ │ │ │ ├── right ordering: +41 │ │ │ │ │ ├── key: (34) │ │ │ │ │ ├── fd: ()-->(46), (34)-->(37), (41)-->(42,43), (43)==(45), (45)==(43), (37)==(41), (41)==(37) - │ │ │ │ │ ├── inner-join + │ │ │ │ │ ├── scan supplier@s_nk + │ │ │ │ │ │ ├── columns: s_suppkey:34(int!null) s_nationkey:37(int!null) + │ │ │ │ │ │ ├── key: (34) + │ │ │ │ │ │ ├── fd: (34)-->(37) + │ │ │ │ │ │ └── ordering: +37 + │ │ │ │ │ ├── sort │ │ │ │ │ │ ├── columns: n_nationkey:41(int!null) n_name:42(string!null) n_regionkey:43(int!null) r_regionkey:45(int!null) r_name:46(string!null) │ │ │ │ │ │ ├── key: (41) │ │ │ │ │ │ ├── fd: ()-->(46), (41)-->(42,43), (43)==(45), (45)==(43) - │ │ │ │ │ │ ├── scan nation - │ │ │ │ │ │ │ ├── columns: n_nationkey:41(int!null) n_name:42(string!null) n_regionkey:43(int!null) - │ │ │ │ │ │ │ ├── key: (41) - │ │ │ │ │ │ │ └── fd: (41)-->(42,43) - │ │ │ │ │ │ ├── select - │ │ │ │ │ │ │ ├── columns: r_regionkey:45(int!null) r_name:46(string!null) - │ │ │ │ │ │ │ ├── key: (45) - │ │ │ │ │ │ │ ├── fd: ()-->(46) - │ │ │ │ │ │ │ ├── scan region - │ │ │ │ │ │ │ │ ├── columns: r_regionkey:45(int!null) r_name:46(string!null) - │ │ │ │ │ │ │ │ ├── key: (45) - │ │ │ │ │ │ │ │ └── fd: (45)-->(46) - │ │ │ │ │ │ │ └── filters - │ │ │ │ │ │ │ └── r_name = 'ASIA' [type=bool, outer=(46), constraints=(/46: [/'ASIA' - /'ASIA']; tight), fd=()-->(46)] - │ │ │ │ │ │ └── filters - │ │ │ │ │ │ └── n_regionkey = r_regionkey [type=bool, outer=(43,45), constraints=(/43: (/NULL - ]; /45: (/NULL - ]), fd=(43)==(45), (45)==(43)] + │ │ │ │ │ │ ├── ordering: +41 opt(46) [actual: +41] + │ │ │ │ │ │ └── inner-join + │ │ │ │ │ │ ├── columns: n_nationkey:41(int!null) n_name:42(string!null) n_regionkey:43(int!null) r_regionkey:45(int!null) r_name:46(string!null) + │ │ │ │ │ │ ├── key: (41) + │ │ │ │ │ │ ├── fd: ()-->(46), (41)-->(42,43), (43)==(45), (45)==(43) + │ │ │ │ │ │ ├── scan nation + │ │ │ │ │ │ │ ├── columns: n_nationkey:41(int!null) n_name:42(string!null) n_regionkey:43(int!null) + │ │ │ │ │ │ │ ├── key: (41) + │ │ │ │ │ │ │ └── fd: (41)-->(42,43) + │ │ │ │ │ │ ├── select + │ │ │ │ │ │ │ ├── columns: r_regionkey:45(int!null) r_name:46(string!null) + │ │ │ │ │ │ │ ├── key: (45) + │ │ │ │ │ │ │ ├── fd: ()-->(46) + │ │ │ │ │ │ │ ├── scan region + │ │ │ │ │ │ │ │ ├── columns: r_regionkey:45(int!null) r_name:46(string!null) + │ │ │ │ │ │ │ │ ├── key: (45) + │ │ │ │ │ │ │ │ └── fd: (45)-->(46) + │ │ │ │ │ │ │ └── filters + │ │ │ │ │ │ │ └── r_name = 'ASIA' [type=bool, outer=(46), constraints=(/46: [/'ASIA' - /'ASIA']; tight), fd=()-->(46)] + │ │ │ │ │ │ └── filters + │ │ │ │ │ │ └── n_regionkey = r_regionkey [type=bool, outer=(43,45), constraints=(/43: (/NULL - ]; /45: (/NULL - ]), fd=(43)==(45), (45)==(43)] │ │ │ │ │ └── filters (true) │ │ │ │ └── filters │ │ │ │ └── l_suppkey = s_suppkey [type=bool, outer=(20,34), constraints=(/20: (/NULL - ]; /34: (/NULL - ]), fd=(20)==(34), (34)==(20)] diff --git a/pkg/sql/opt/xform/testdata/rules/join b/pkg/sql/opt/xform/testdata/rules/join index 00d22c265e4e..beaba5879beb 100644 --- a/pkg/sql/opt/xform/testdata/rules/join +++ b/pkg/sql/opt/xform/testdata/rules/join @@ -1495,7 +1495,7 @@ memo (optimized, ~14KB, required=[presentation: q:2,r:3,s:4]) ├── G1: (select G2 G3) (lookup-join G4 G5 pqr,keyCols=[1],outCols=(2-4)) (select G6 G7) (select G8 G9) (select G10 G9) │ └── [presentation: q:2,r:3,s:4] │ ├── best: (lookup-join G4 G5 pqr,keyCols=[1],outCols=(2-4)) - │ └── cost: 0.72 + │ └── cost: 0.82 ├── G2: (scan pqr,cols=(2-4)) │ └── [] │ ├── best: (scan pqr,cols=(2-4)) @@ -1879,11 +1879,11 @@ memo (optimized, ~11KB, required=[presentation: a:1]) ├── G1: (project G2 G3 a) │ └── [presentation: a:1] │ ├── best: (project G2 G3 a) - │ └── cost: 88.05 + │ └── cost: 100.40 ├── G2: (select G4 G5) (lookup-join G6 G5 t5,keyCols=[1],outCols=(1,2)) (select G7 G5) │ └── [] │ ├── best: (lookup-join G6 G5 t5,keyCols=[1],outCols=(1,2)) - │ └── cost: 87.92 + │ └── cost: 100.27 ├── G3: (projections) ├── G4: (scan t5,cols=(1,2)) │ └── [] diff --git a/pkg/sql/opt/xform/testdata/rules/join_order b/pkg/sql/opt/xform/testdata/rules/join_order index 9c9fdfd06d56..ba9eaec39350 100644 --- a/pkg/sql/opt/xform/testdata/rules/join_order +++ b/pkg/sql/opt/xform/testdata/rules/join_order @@ -153,7 +153,7 @@ memo (optimized, ~18KB, 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)) │ └── [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)) - │ └── cost: 11.19 + │ └── cost: 13.19 ├── G2: (scan bx) │ ├── [ordering: +1] │ │ ├── best: (scan bx) @@ -164,7 +164,7 @@ memo (optimized, ~18KB, required=[presentation: b:1,x:2,c:3,y:4,a:5,b:6,c:7,d:8] ├── G3: (inner-join G6 G9 G8) (inner-join G9 G6 G8) (merge-join G6 G9 G5 inner-join,+3,+7) (lookup-join G9 G5 cy,keyCols=[7],outCols=(3-8)) │ └── [] │ ├── best: (lookup-join G9 G5 cy,keyCols=[7],outCols=(3-8)) - │ └── cost: 6.14 + │ └── cost: 7.14 ├── G4: (filters G12) ├── G5: (filters) ├── G6: (scan cy) @@ -177,7 +177,7 @@ memo (optimized, ~18KB, required=[presentation: b:1,x:2,c:3,y:4,a:5,b:6,c:7,d:8] ├── G7: (inner-join G9 G2 G4) (inner-join G2 G9 G4) (lookup-join G9 G5 bx,keyCols=[6],outCols=(1,2,5-8)) (merge-join G2 G9 G5 inner-join,+1,+6) │ └── [] │ ├── best: (lookup-join G9 G5 bx,keyCols=[6],outCols=(1,2,5-8)) - │ └── cost: 6.14 + │ └── cost: 7.14 ├── G8: (filters G13) ├── G9: (select G14 G15) (scan abc,constrained) │ └── []