diff --git a/pkg/sql/exec_util.go b/pkg/sql/exec_util.go index f7c1283eb200..5013c7d2c6b0 100644 --- a/pkg/sql/exec_util.go +++ b/pkg/sql/exec_util.go @@ -3412,6 +3412,10 @@ func (m *sessionDataMutator) SetOptimizerUseLimitOrderingForStreamingGroupBy(val m.data.OptimizerUseLimitOrderingForStreamingGroupBy = val } +func (m *sessionDataMutator) SetOptimizerUseImprovedSplitDisjunctionForJoins(val bool) { + m.data.OptimizerUseImprovedSplitDisjunctionForJoins = val +} + // Utility functions related to scrubbing sensitive information on SQL Stats. // quantizeCounts ensures that the Count field in the diff --git a/pkg/sql/logictest/testdata/logic_test/information_schema b/pkg/sql/logictest/testdata/logic_test/information_schema index 2f96408959fa..5132f1927c51 100644 --- a/pkg/sql/logictest/testdata/logic_test/information_schema +++ b/pkg/sql/logictest/testdata/logic_test/information_schema @@ -5003,6 +5003,7 @@ optimizer on optimizer_use_forecasts on optimizer_use_histograms on optimizer_use_improved_disjunction_stats on +optimizer_use_improved_split_disjunction_for_joins on optimizer_use_limit_ordering_for_streaming_group_by on optimizer_use_multicol_stats on optimizer_use_not_visible_indexes off diff --git a/pkg/sql/logictest/testdata/logic_test/pg_catalog b/pkg/sql/logictest/testdata/logic_test/pg_catalog index e59d8a3f9c3f..e314d67630f7 100644 --- a/pkg/sql/logictest/testdata/logic_test/pg_catalog +++ b/pkg/sql/logictest/testdata/logic_test/pg_catalog @@ -2642,6 +2642,7 @@ opt_split_scan_limit 2048 NULL optimizer_use_forecasts on NULL NULL NULL string optimizer_use_histograms on NULL NULL NULL string optimizer_use_improved_disjunction_stats on NULL NULL NULL string +optimizer_use_improved_split_disjunction_for_joins on NULL NULL NULL string optimizer_use_limit_ordering_for_streaming_group_by on NULL NULL NULL string optimizer_use_multicol_stats on NULL NULL NULL string optimizer_use_not_visible_indexes off NULL NULL NULL string @@ -2786,6 +2787,7 @@ opt_split_scan_limit 2048 NULL optimizer_use_forecasts on NULL user NULL on on optimizer_use_histograms on NULL user NULL on on optimizer_use_improved_disjunction_stats on NULL user NULL on on +optimizer_use_improved_split_disjunction_for_joins on NULL user NULL on on optimizer_use_limit_ordering_for_streaming_group_by on NULL user NULL on on optimizer_use_multicol_stats on NULL user NULL on on optimizer_use_not_visible_indexes off NULL user NULL off off @@ -2929,6 +2931,7 @@ optimizer NULL NULL NULL optimizer_use_forecasts NULL NULL NULL NULL NULL optimizer_use_histograms NULL NULL NULL NULL NULL optimizer_use_improved_disjunction_stats NULL NULL NULL NULL NULL +optimizer_use_improved_split_disjunction_for_joins NULL NULL NULL NULL NULL optimizer_use_limit_ordering_for_streaming_group_by NULL NULL NULL NULL NULL optimizer_use_multicol_stats NULL NULL NULL NULL NULL optimizer_use_not_visible_indexes NULL NULL NULL NULL NULL diff --git a/pkg/sql/logictest/testdata/logic_test/show_source b/pkg/sql/logictest/testdata/logic_test/show_source index fe66d33f68d7..aa393f330d91 100644 --- a/pkg/sql/logictest/testdata/logic_test/show_source +++ b/pkg/sql/logictest/testdata/logic_test/show_source @@ -110,6 +110,7 @@ opt_split_scan_limit 2048 optimizer_use_forecasts on optimizer_use_histograms on optimizer_use_improved_disjunction_stats on +optimizer_use_improved_split_disjunction_for_joins on optimizer_use_limit_ordering_for_streaming_group_by on optimizer_use_multicol_stats on optimizer_use_not_visible_indexes off diff --git a/pkg/sql/opt/exec/execbuilder/testdata/tpch_vec b/pkg/sql/opt/exec/execbuilder/testdata/tpch_vec index 878b2c0c45ca..6859b6dedc08 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/tpch_vec +++ b/pkg/sql/opt/exec/execbuilder/testdata/tpch_vec @@ -20925,48 +20925,31 @@ EXPLAIN (VEC) SELECT sum(l_extendedprice* (1 - l_discount)) AS revenue FROM line └ *colexec.orderedAggregator └ *colexecproj.projMultFloat64Float64Op └ *colexecprojconst.projMinusFloat64ConstFloat64Op - └ *colexec.caseOp - ├ *colexec.bufferOp - │ └ *colexecjoin.hashJoiner - │ ├ *colexecsel.selEQBytesBytesConstOp - │ │ └ *colexec.selectInOpBytes - │ │ └ *colfetcher.ColBatchScan - │ └ *colexecsel.selGEInt64Int64ConstOp - │ └ *colfetcher.ColBatchScan - ├ *colexecbase.constBoolOp - │ └ *colexec.orProjOp - │ ├ *colexec.bufferOp - │ ├ *colexec.andProjOp - │ │ ├ *colexec.andProjOp - │ │ │ ├ *colexec.andProjOp - │ │ │ │ ├ *colexec.andProjOp - │ │ │ │ │ ├ *colexecprojconst.projEQBytesBytesConstOp - │ │ │ │ │ └ *colexec.projectInOpBytes - │ │ │ │ └ *colexecprojconst.projGEFloat64Float64ConstOp - │ │ │ └ *colexecprojconst.projLEFloat64Float64ConstOp - │ │ └ *colexecprojconst.projLEInt64Int64ConstOp - │ └ *colexec.andProjOp - │ ├ *colexec.andProjOp - │ │ ├ *colexec.andProjOp - │ │ │ ├ *colexec.andProjOp - │ │ │ │ ├ *colexecprojconst.projEQBytesBytesConstOp - │ │ │ │ └ *colexec.projectInOpBytes - │ │ │ └ *colexecprojconst.projGEFloat64Float64ConstOp - │ │ └ *colexecprojconst.projLEFloat64Float64ConstOp - │ └ *colexecprojconst.projLEInt64Int64ConstOp - ├ *colexecbase.constBoolOp - │ └ *colexec.andProjOp - │ ├ *colexec.bufferOp - │ ├ *colexec.andProjOp - │ │ ├ *colexec.andProjOp - │ │ │ ├ *colexec.andProjOp - │ │ │ │ ├ *colexecprojconst.projEQBytesBytesConstOp - │ │ │ │ └ *colexec.projectInOpBytes - │ │ │ └ *colexecprojconst.projGEFloat64Float64ConstOp - │ │ └ *colexecprojconst.projLEFloat64Float64ConstOp - │ └ *colexecprojconst.projLEInt64Int64ConstOp - └ *colexecbase.constBoolOp - └ *colexec.bufferOp + └ *colexec.UnorderedDistinct + └ *colexec.SerialUnorderedSynchronizer + ├ *rowexec.joinReader + │ └ *rowexec.joinReader + │ └ *colexec.selectInOpBytes + │ └ *colexecsel.selEQBytesBytesConstOp + │ └ *colexecsel.selLEInt64Int64ConstOp + │ └ *colexecsel.selGEInt64Int64ConstOp + │ └ *colfetcher.ColBatchScan + └ *colexec.UnorderedDistinct + └ *colexec.SerialUnorderedSynchronizer + ├ *rowexec.joinReader + │ └ *rowexec.joinReader + │ └ *colexec.selectInOpBytes + │ └ *colexecsel.selEQBytesBytesConstOp + │ └ *colexecsel.selLEInt64Int64ConstOp + │ └ *colexecsel.selGEInt64Int64ConstOp + │ └ *colfetcher.ColBatchScan + └ *rowexec.joinReader + └ *rowexec.joinReader + └ *colexec.selectInOpBytes + └ *colexecsel.selEQBytesBytesConstOp + └ *colexecsel.selLEInt64Int64ConstOp + └ *colexecsel.selGEInt64Int64ConstOp + └ *colfetcher.ColBatchScan # Query 20 query T diff --git a/pkg/sql/opt/memo/memo.go b/pkg/sql/opt/memo/memo.go index 4362bab0b1a1..c345c029095f 100644 --- a/pkg/sql/opt/memo/memo.go +++ b/pkg/sql/opt/memo/memo.go @@ -161,6 +161,7 @@ type Memo struct { allowOrdinalColumnReferences bool useImprovedDisjunctionStats bool useLimitOrderingForStreamingGroupBy bool + useImprovedSplitDisjunctionForJoins bool // curRank is the highest currently in-use scalar expression rank. curRank opt.ScalarRank @@ -217,6 +218,7 @@ func (m *Memo) Init(ctx context.Context, evalCtx *eval.Context) { allowOrdinalColumnReferences: evalCtx.SessionData().AllowOrdinalColumnReferences, useImprovedDisjunctionStats: evalCtx.SessionData().OptimizerUseImprovedDisjunctionStats, useLimitOrderingForStreamingGroupBy: evalCtx.SessionData().OptimizerUseLimitOrderingForStreamingGroupBy, + useImprovedSplitDisjunctionForJoins: evalCtx.SessionData().OptimizerUseImprovedSplitDisjunctionForJoins, } m.metadata.Init() m.logPropsBuilder.init(ctx, evalCtx, m) @@ -356,7 +358,8 @@ func (m *Memo) IsStale( m.variableInequalityLookupJoinEnabled != evalCtx.SessionData().VariableInequalityLookupJoinEnabled || m.allowOrdinalColumnReferences != evalCtx.SessionData().AllowOrdinalColumnReferences || m.useImprovedDisjunctionStats != evalCtx.SessionData().OptimizerUseImprovedDisjunctionStats || - m.useLimitOrderingForStreamingGroupBy != evalCtx.SessionData().OptimizerUseLimitOrderingForStreamingGroupBy { + m.useLimitOrderingForStreamingGroupBy != evalCtx.SessionData().OptimizerUseLimitOrderingForStreamingGroupBy || + m.useImprovedSplitDisjunctionForJoins != evalCtx.SessionData().OptimizerUseImprovedSplitDisjunctionForJoins { return true, nil } diff --git a/pkg/sql/opt/memo/memo_test.go b/pkg/sql/opt/memo/memo_test.go index 65a05ae8dddd..02a33bba4328 100644 --- a/pkg/sql/opt/memo/memo_test.go +++ b/pkg/sql/opt/memo/memo_test.go @@ -312,6 +312,12 @@ func TestMemoIsStale(t *testing.T) { evalCtx.SessionData().OptimizerUseLimitOrderingForStreamingGroupBy = false notStale() + // Stale use improved split disjunction for joins. + evalCtx.SessionData().OptimizerUseImprovedSplitDisjunctionForJoins = true + stale() + evalCtx.SessionData().OptimizerUseImprovedSplitDisjunctionForJoins = false + notStale() + // Stale testing_optimizer_random_seed. evalCtx.SessionData().TestingOptimizerRandomSeed = 100 stale() diff --git a/pkg/sql/opt/memo/testdata/stats/join b/pkg/sql/opt/memo/testdata/stats/join index 875d1da25421..5f82f52256eb 100644 --- a/pkg/sql/opt/memo/testdata/stats/join +++ b/pkg/sql/opt/memo/testdata/stats/join @@ -1648,20 +1648,92 @@ ALTER TABLE uv INJECT STATISTICS '[ opt SELECT * FROM xysd, uv WHERE (s = 'foo' AND u = 3 AND v = 4) OR (s = 'bar' AND u = 5 AND v = 6) ---- -inner-join (cross) +project ├── columns: x:1(int!null) y:2(int) s:3(string!null) d:4(decimal!null) u:7(int!null) v:8(int!null) ├── stats: [rows=59573.61, distinct(3)=2, null(3)=0, distinct(7)=2, null(7)=0, distinct(8)=2, null(8)=0, distinct(7,8)=2.18365, null(7,8)=0] ├── fd: (1)-->(2-4), (3,4)-->(1,2) - ├── scan uv - │ ├── columns: u:7(int) v:8(int!null) - │ └── stats: [rows=10000, distinct(7)=500, null(7)=0, distinct(8)=100, null(8)=0, distinct(7,8)=550, null(7,8)=0] - ├── scan xysd - │ ├── columns: x:1(int!null) y:2(int) s:3(string) d:4(decimal!null) - │ ├── stats: [rows=5000, distinct(1)=5000, null(1)=0, distinct(3)=10, null(3)=0, distinct(4)=500, null(4)=0] - │ ├── key: (1) - │ └── fd: (1)-->(2-4), (3,4)~~>(1,2) - └── filters - └── (((s:3 = 'foo') AND (u:7 = 3)) AND (v:8 = 4)) OR (((s:3 = 'bar') AND (u:7 = 5)) AND (v:8 = 6)) [type=bool, outer=(3,7,8), constraints=(/3: [/'bar' - /'bar'] [/'foo' - /'foo']; /7: [/3 - /3] [/5 - /5]; /8: [/4 - /4] [/6 - /6])] + └── distinct-on + ├── columns: x:1(int!null) y:2(int) s:3(string!null) d:4(decimal!null) u:7(int!null) v:8(int!null) rowid:9(int!null) + ├── grouping columns: x:1(int!null) rowid:9(int!null) + ├── stats: [rows=16383.64, distinct(1,9)=16383.6, null(1,9)=0] + ├── key: (1,9) + ├── fd: (1,9)-->(2-4,7,8) + ├── union-all + │ ├── columns: x:1(int!null) y:2(int) s:3(string!null) d:4(decimal!null) u:7(int!null) v:8(int!null) rowid:9(int!null) + │ ├── left columns: x:12(int) y:13(int) s:14(string) d:15(decimal) u:18(int) v:19(int) rowid:20(int) + │ ├── right columns: x:23(int) y:24(int) s:25(string) d:26(decimal) u:29(int) v:30(int) rowid:31(int) + │ ├── stats: [rows=16383.64, distinct(1,9)=16383.6, null(1,9)=0] + │ ├── inner-join (cross) + │ │ ├── columns: x:12(int!null) y:13(int) s:14(string!null) d:15(decimal!null) u:18(int!null) v:19(int!null) rowid:20(int!null) + │ │ ├── stats: [rows=8191.818, distinct(12,20)=8191.82, null(12,20)=0] + │ │ ├── key: (12,20) + │ │ ├── fd: ()-->(14,18,19), (12)-->(13,15), (15)-->(12,13) + │ │ ├── index-join xysd + │ │ │ ├── columns: x:12(int!null) y:13(int) s:14(string!null) d:15(decimal!null) + │ │ │ ├── stats: [rows=500, distinct(12)=500, null(12)=0, distinct(14)=1, null(14)=0] + │ │ │ ├── key: (12) + │ │ │ ├── fd: ()-->(14), (12)-->(13,15), (15)-->(12,13) + │ │ │ └── scan xysd@xysd_s_d_key + │ │ │ ├── columns: x:12(int!null) s:14(string!null) d:15(decimal!null) + │ │ │ ├── constraint: /-14/15: [/'foo' - /'foo'] + │ │ │ ├── stats: [rows=500, distinct(14)=1, null(14)=0] + │ │ │ ├── key: (12) + │ │ │ └── fd: ()-->(14), (12)-->(15), (15)-->(12) + │ │ ├── select + │ │ │ ├── columns: u:18(int!null) v:19(int!null) rowid:20(int!null) + │ │ │ ├── stats: [rows=16.38364, distinct(18)=1, null(18)=0, distinct(19)=1, null(19)=0, distinct(20)=16.3836, null(20)=0, distinct(18,19)=1, null(18,19)=0] + │ │ │ ├── key: (20) + │ │ │ ├── fd: ()-->(18,19) + │ │ │ ├── scan uv + │ │ │ │ ├── columns: u:18(int) v:19(int!null) rowid:20(int!null) + │ │ │ │ ├── stats: [rows=10000, distinct(18)=500, null(18)=0, distinct(19)=100, null(19)=0, distinct(20)=10000, null(20)=0, distinct(18,19)=550, null(18,19)=0] + │ │ │ │ ├── key: (20) + │ │ │ │ └── fd: (20)-->(18,19) + │ │ │ └── filters + │ │ │ ├── u:18 = 3 [type=bool, outer=(18), constraints=(/18: [/3 - /3]; tight), fd=()-->(18)] + │ │ │ └── v:19 = 4 [type=bool, outer=(19), constraints=(/19: [/4 - /4]; tight), fd=()-->(19)] + │ │ └── filters (true) + │ └── inner-join (cross) + │ ├── columns: x:23(int!null) y:24(int) s:25(string!null) d:26(decimal!null) u:29(int!null) v:30(int!null) rowid:31(int!null) + │ ├── stats: [rows=8191.818, distinct(23,31)=8191.82, null(23,31)=0] + │ ├── key: (23,31) + │ ├── fd: ()-->(25,29,30), (23)-->(24,26), (26)-->(23,24) + │ ├── index-join xysd + │ │ ├── columns: x:23(int!null) y:24(int) s:25(string!null) d:26(decimal!null) + │ │ ├── stats: [rows=500, distinct(23)=500, null(23)=0, distinct(25)=1, null(25)=0] + │ │ ├── key: (23) + │ │ ├── fd: ()-->(25), (23)-->(24,26), (26)-->(23,24) + │ │ └── scan xysd@xysd_s_d_key + │ │ ├── columns: x:23(int!null) s:25(string!null) d:26(decimal!null) + │ │ ├── constraint: /-25/26: [/'bar' - /'bar'] + │ │ ├── stats: [rows=500, distinct(25)=1, null(25)=0] + │ │ ├── key: (23) + │ │ └── fd: ()-->(25), (23)-->(26), (26)-->(23) + │ ├── select + │ │ ├── columns: u:29(int!null) v:30(int!null) rowid:31(int!null) + │ │ ├── stats: [rows=16.38364, distinct(29)=1, null(29)=0, distinct(30)=1, null(30)=0, distinct(31)=16.3836, null(31)=0, distinct(29,30)=1, null(29,30)=0] + │ │ ├── key: (31) + │ │ ├── fd: ()-->(29,30) + │ │ ├── scan uv + │ │ │ ├── columns: u:29(int) v:30(int!null) rowid:31(int!null) + │ │ │ ├── stats: [rows=10000, distinct(29)=500, null(29)=0, distinct(30)=100, null(30)=0, distinct(31)=10000, null(31)=0, distinct(29,30)=550, null(29,30)=0] + │ │ │ ├── key: (31) + │ │ │ └── fd: (31)-->(29,30) + │ │ └── filters + │ │ ├── u:29 = 5 [type=bool, outer=(29), constraints=(/29: [/5 - /5]; tight), fd=()-->(29)] + │ │ └── v:30 = 6 [type=bool, outer=(30), constraints=(/30: [/6 - /6]; tight), fd=()-->(30)] + │ └── filters (true) + └── aggregations + ├── const-agg [as=y:2, type=int, outer=(2)] + │ └── y:2 [type=int] + ├── const-agg [as=s:3, type=string, outer=(3)] + │ └── s:3 [type=string] + ├── const-agg [as=d:4, type=decimal, outer=(4)] + │ └── d:4 [type=decimal] + ├── const-agg [as=u:7, type=int, outer=(7)] + │ └── u:7 [type=int] + └── const-agg [as=v:8, type=int, outer=(8)] + └── v:8 [type=int] # Test selectivity of ORed join predicates # Estimate of # rows should be low, and nowhere near the no-stats diff --git a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q19 b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q19 index b3f6b29d1b1f..24f96fd2f6d3 100644 --- a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q19 +++ b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q19 @@ -67,67 +67,233 @@ scalar-group-by │ ├── columns: column30:30(float!null) │ ├── immutable │ ├── stats: [rows=185.5999, distinct(30)=185.559, null(30)=0] - │ ├── inner-join (hash) - │ │ ├── save-table-name: q19_inner_join_3 + │ ├── project + │ │ ├── save-table-name: q19_project_3 │ │ ├── columns: l_partkey:2(int!null) l_quantity:5(float!null) l_extendedprice:6(float!null) l_discount:7(float!null) l_shipinstruct:14(char!null) l_shipmode:15(char!null) p_partkey:19(int!null) p_brand:22(char!null) p_size:24(int!null) p_container:25(char!null) - │ │ ├── multiplicity: left-rows(zero-or-one), right-rows(zero-or-more) │ │ ├── stats: [rows=185.5999, distinct(2)=185.6, null(2)=0, distinct(5)=5.55556, null(5)=0, distinct(6)=185.55, null(6)=0, distinct(7)=11, null(7)=0, distinct(14)=1, null(14)=0, distinct(15)=2, null(15)=0, distinct(19)=185.6, null(19)=0, distinct(22)=3, null(22)=0, distinct(24)=16.6667, null(24)=0, distinct(25)=12, null(25)=0, distinct(6,7)=185.559, null(6,7)=0, distinct(22,24,25)=185.6, null(22,24,25)=0] │ │ ├── fd: ()-->(14), (19)-->(22,24,25), (2)==(19), (19)==(2) - │ │ ├── select - │ │ │ ├── save-table-name: q19_select_4 - │ │ │ ├── columns: l_partkey:2(int!null) l_quantity:5(float!null) l_extendedprice:6(float!null) l_discount:7(float!null) l_shipinstruct:14(char!null) l_shipmode:15(char!null) - │ │ │ ├── stats: [rows=416015.1, distinct(2)=176353, null(2)=0, distinct(5)=50, null(5)=0, distinct(6)=344687, null(6)=0, distinct(7)=11, null(7)=0, distinct(14)=1, null(14)=0, distinct(15)=2, null(15)=0, distinct(6,7)=416015, null(6,7)=0, distinct(14,15)=2, null(14,15)=0] - │ │ │ │ histogram(14)= 0 4.1602e+05 - │ │ │ │ <--- 'DELIVER IN PERSON' - │ │ │ │ histogram(15)= 0 2.0613e+05 0 2.0988e+05 - │ │ │ │ <---- 'AIR' ----- 'AIR REG' - │ │ │ ├── fd: ()-->(14) - │ │ │ ├── scan lineitem - │ │ │ │ ├── save-table-name: q19_scan_5 - │ │ │ │ ├── columns: l_partkey:2(int!null) l_quantity:5(float!null) l_extendedprice:6(float!null) l_discount:7(float!null) l_shipinstruct:14(char!null) l_shipmode:15(char!null) - │ │ │ │ └── stats: [rows=6001215, distinct(2)=199241, null(2)=0, distinct(5)=50, null(5)=0, distinct(6)=925955, null(6)=0, distinct(7)=11, null(7)=0, distinct(14)=4, null(14)=0, distinct(15)=7, null(15)=0, distinct(6,7)=6.00122e+06, null(6,7)=0, distinct(14,15)=28, null(14,15)=0] - │ │ │ │ histogram(2)= 0 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 1200 29406 600 29406 600 29406 600 29406 600 28806 1200 28806 1200 29406 600 29406 600 29406 600 29406 600 28806 1200 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 1200 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 1200 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 28806 1200 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 1200 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 29406 600 30006 600 30006 600 30006 600 30006 600 30006 600 30006 600 30006 600 30006 600 30006 600 30006 600 30006 600 30006 600 30006 600 30006 600 30006 600 30006 600 30006 600 30006 600 30006 600 30006 600 30006 600 30006 600 30006 600 30006 600 30006 600 30006 600 30006 600 30006 600 30006 600 30006 600 30006 600 30006 600 30006 600 30006 600 30006 600 30006 600 30006 600 29406 1200 30006 600 30006 600 30006 600 30006 600 30006 600 30006 600 30006 600 - │ │ │ │ <--- 1 ------- 1010 ------- 2021 ------- 2991 ------- 3884 ------- 5037 ------- 6245 ------- 7212 ------- 8245 ------- 9154 ------- 10259 ------- 11255 ------- 12046 ------- 13289 ------- 14181 ------- 15137 ------- 16032 ------- 17172 ------- 18410 ------- 19491 ------- 20333 ------- 21223 ------- 22309 ------- 23246 ------- 24374 ------- 25350 ------- 26537 ------- 27310 ------- 28392 ------- 29739 ------- 30950 ------- 31941 ------- 33097 ------- 33985 ------- 34802 ------- 35684 ------- 36612 ------- 37384 ------- 38411 ------- 39549 ------- 40551 ------- 41405 ------- 42339 ------- 43330 ------- 44225 ------- 45263 ------- 46110 ------- 47040 ------- 48028 ------- 48915 ------- 49799 ------- 50642 ------- 51505 ------- 52630 ------- 53961 ------- 54897 ------- 55868 ------- 56689 ------- 57415 ------- 58518 ------- 59669 ------- 60830 ------- 61995 ------- 63158 ------- 63865 ------- 64886 ------- 65607 ------- 66597 ------- 67661 ------- 68633 ------- 69805 ------- 70863 ------- 71876 ------- 73029 ------- 74162 ------- 74986 ------- 76076 ------- 76985 ------- 77776 ------- 78508 ------- 79548 ------- 80396 ------- 81456 ------- 82333 ------- 83231 ------- 84386 ------- 85300 ------- 86272 ------- 87463 ------- 88529 ------- 89522 ------- 90306 ------- 91426 ------- 92473 ------- 93517 ------- 94593 ------- 95575 ------- 96574 ------- 97504 ------- 98485 ------- 99367 ------- 100491 ------- 101417 ------- 102577 ------- 103708 ------- 104704 ------- 105507 ------- 106609 ------- 107562 ------- 108737 ------- 109864 ------- 110773 ------- 111601 ------- 112703 ------- 113643 ------- 114751 ------- 115554 ------- 116375 ------- 117312 ------- 118175 ------- 119101 ------- 120011 ------- 120960 ------- 121864 ------- 122791 ------- 123795 ------- 124770 ------- 125769 ------- 126755 ------- 127543 ------- 128685 ------- 129867 ------- 130997 ------- 131919 ------- 133103 ------- 134064 ------- 134881 ------- 135973 ------- 136848 ------- 137915 ------- 139143 ------- 140073 ------- 141060 ------- 141836 ------- 142825 ------- 143705 ------- 144771 ------- 146062 ------- 147034 ------- 147999 ------- 148876 ------- 149779 ------- 151087 ------- 152065 ------- 153127 ------- 154130 ------- 155112 ------- 156203 ------- 157156 ------- 158209 ------- 159141 ------- 160322 ------- 161399 ------- 162398 ------- 163341 ------- 164401 ------- 165792 ------- 166940 ------- 167888 ------- 168873 ------- 169587 ------- 170828 ------- 172084 ------- 172929 ------- 174080 ------- 175179 ------- 176285 ------- 177380 ------- 178290 ------- 179162 ------- 180295 ------- 181480 ------- 182534 ------- 183776 ------- 184856 ------- 185893 ------- 186994 ------- 187717 ------- 188760 ------- 189696 ------- 190738 ------- 191579 ------- 192799 ------- 193728 ------- 194863 ------- 195849 ------- 196821 ------- 197744 ------- 198749 ------- 199990 - │ │ │ │ histogram(5)= 0 1.1342e+05 5.766e+06 1.2182e+05 - │ │ │ │ <----- 1.0 ---------------- 50.0 -- - │ │ │ │ histogram(6)= 0 600 6e+06 600 - │ │ │ │ <--- 929.02 ------- 104249.0 - │ │ │ │ histogram(7)= 0 5.4971e+05 4.9108e+06 5.4071e+05 - │ │ │ │ <----- 0.0 ----------------- 0.1 --- - │ │ │ │ histogram(14)= 0 1.5093e+06 2.949e+06 1.5429e+06 - │ │ │ │ <--- 'COLLECT COD' ----------- 'TAKE BACK RETURN' - │ │ │ │ histogram(15)= 0 8.3897e+05 4.2711e+06 8.9118e+05 - │ │ │ │ <---- 'AIR' -------------- 'TRUCK' - - │ │ │ └── filters - │ │ │ ├── l_shipmode:15 IN ('AIR', 'AIR REG') [type=bool, outer=(15), constraints=(/15: [/'AIR' - /'AIR'] [/'AIR REG' - /'AIR REG']; tight)] - │ │ │ └── l_shipinstruct:14 = 'DELIVER IN PERSON' [type=bool, outer=(14), constraints=(/14: [/'DELIVER IN PERSON' - /'DELIVER IN PERSON']; tight), fd=()-->(14)] - │ │ ├── select - │ │ │ ├── save-table-name: q19_select_6 - │ │ │ ├── columns: p_partkey:19(int!null) p_brand:22(char!null) p_size:24(int!null) p_container:25(char!null) - │ │ │ ├── stats: [rows=200000, distinct(19)=199241, null(19)=0, distinct(22)=25, null(22)=0, distinct(24)=50, null(24)=0, distinct(25)=40, null(25)=0, distinct(22,24,25)=50000, null(22,24,25)=0] - │ │ │ │ histogram(24)= 0 4240 1.9186e+05 3900 - │ │ │ │ <--- 1 ------------- 50 - │ │ │ ├── key: (19) - │ │ │ ├── fd: (19)-->(22,24,25) - │ │ │ ├── scan part - │ │ │ │ ├── save-table-name: q19_scan_7 - │ │ │ │ ├── columns: p_partkey:19(int!null) p_brand:22(char!null) p_size:24(int!null) p_container:25(char!null) - │ │ │ │ ├── stats: [rows=200000, distinct(19)=199241, null(19)=0, distinct(22)=25, null(22)=0, distinct(24)=50, null(24)=0, distinct(25)=40, null(25)=0, distinct(22,24,25)=50000, null(22,24,25)=0] - │ │ │ │ │ histogram(19)= 0 3.9982 929.57 3.9982 1135.5 3.9982 923.58 3.9982 1036.5 3.9982 964.56 3.9982 953.56 3.9982 899.59 3.9982 1152.5 3.9982 1118.5 3.9982 1137.5 3.9982 1129.5 3.9982 1136.5 3.9982 983.55 3.9982 983.55 3.9982 1028.5 3.9982 1007.5 3.9982 1036.5 3.9982 884.59 3.9982 985.55 3.9982 970.55 3.9982 1036.5 3.9982 943.57 3.9982 1020.5 3.9982 1001.5 3.9982 1001.5 3.9982 954.56 3.9982 1036.5 3.9982 990.54 3.9982 928.57 3.9982 1010.5 3.9982 892.59 3.9982 960.56 3.9982 1059.5 3.9982 947.56 3.9982 906.58 3.9982 935.57 3.9982 860.6 3.9982 971.55 3.9982 1067.5 3.9982 994.54 3.9982 961.56 3.9982 943.57 3.9982 901.59 3.9982 972.55 3.9982 956.56 3.9982 1106.5 3.9982 1152.5 3.9982 967.55 3.9982 943.57 3.9982 916.58 3.9982 1076.5 3.9982 933.57 3.9982 1108.5 3.9982 1081.5 3.9982 975.55 3.9982 1021.5 3.9982 1034.5 3.9982 905.58 3.9982 902.58 3.9982 966.56 3.9982 1080.5 3.9982 927.57 3.9982 936.57 3.9982 1008.5 3.9982 1033.5 3.9982 903.58 3.9982 944.57 3.9982 908.58 3.9982 1008.5 3.9982 1059.5 3.9982 1079.5 3.9982 911.58 3.9982 1107.5 3.9982 992.54 3.9982 975.55 3.9982 1156.5 3.9982 1042.5 3.9982 1072.5 3.9982 916.58 3.9982 1022.5 3.9982 999.54 3.9982 966.56 3.9982 936.57 3.9982 934.57 3.9982 969.55 3.9982 1136.5 3.9982 997.54 3.9982 991.54 3.9982 1002.5 3.9982 1047.5 3.9982 1059.5 3.9982 972.55 3.9982 918.58 3.9982 959.56 3.9982 1083.5 3.9982 934.57 3.9982 900.59 3.9982 970.55 3.9982 952.56 3.9982 1063.5 3.9982 870.6 3.9982 958.56 3.9982 1029.5 3.9982 943.57 3.9982 872.6 3.9982 972.55 3.9982 1009.5 3.9982 875.6 3.9982 1127.5 3.9982 987.55 3.9982 1156.5 3.9982 971.55 3.9982 1155.5 3.9982 930.57 3.9982 1051.5 3.9982 1044.5 3.9982 867.6 3.9982 898.59 3.9982 926.57 3.9982 965.56 3.9982 1027.5 3.9982 993.54 3.9982 927.57 3.9982 973.55 3.9982 934.57 3.9982 951.56 3.9982 1007.5 3.9982 1124.5 3.9982 936.57 3.9982 1050.5 3.9982 1075.5 3.9982 1028.5 3.9982 872.6 3.9982 960.56 3.9982 1014.5 3.9982 1017.5 3.9982 860.6 3.9982 1039.5 3.9982 1059.5 3.9982 921.58 3.9982 936.57 3.9982 1024.5 3.9982 970.55 3.9982 1047.5 3.9982 917.58 3.9982 948.56 3.9982 978.55 3.9982 993.54 3.9982 1121.5 3.9982 944.57 3.9982 1005.5 3.9982 1037.5 3.9982 1261.4 3.9982 1062.5 3.9982 925.57 3.9982 976.55 3.9982 892.59 3.9982 972.55 3.9982 1135.5 3.9982 1044.5 3.9982 959.56 3.9982 990.54 3.9982 993.54 3.9982 1130.5 3.9982 919.58 3.9982 1025.5 3.9982 1001.5 3.9982 974.55 3.9982 1061.5 3.9982 1166.5 3.9982 1017.5 3.9982 1063.5 3.9982 1188.5 3.9982 964.56 3.9982 1047.5 3.9982 1210.4 3.9982 1087.5 3.9982 1151.5 3.9982 1096.5 3.9982 957.56 3.9982 1073.5 3.9982 925.57 3.9982 1051.5 3.9982 930.57 3.9982 1005.5 3.9982 977.55 3.9982 963.56 3.9982 1005.5 3.9982 954.56 3.9982 1025.5 3.9982 1039.5 3.9982 985.55 3.9982 923.58 3.9982 1087.5 3.9982 958.56 3.9982 1066.5 3.9982 1110.5 3.9982 934.57 3.9982 946.56 3.9982 - │ │ │ │ │ <---- 23 --------- 901 --------- 2150 -------- 3016 -------- 4093 -------- 5038 -------- 5962 -------- 6778 -------- 8056 -------- 9277 -------- 10530 -------- 11769 -------- 13020 -------- 14001 -------- 14982 -------- 16046 -------- 17072 -------- 18149 -------- 18935 -------- 19920 -------- 20876 -------- 21953 -------- 22859 -------- 23908 -------- 24923 -------- 25938 -------- 26865 -------- 27943 -------- 28938 -------- 29813 -------- 30844 -------- 31647 -------- 32585 -------- 33704 -------- 34617 -------- 35448 -------- 36338 ------- 37071 -------- 38029 -------- 39162 -------- 40163 -------- 41103 -------- 42008 -------- 42828 -------- 43789 -------- 44720 -------- 45920 -------- 47197 -------- 48149 -------- 49054 -------- 49906 -------- 51054 -------- 51940 -------- 53144 -------- 54301 -------- 55267 -------- 56318 -------- 57393 -------- 58223 -------- 59046 -------- 59995 -------- 61150 -------- 62024 -------- 62915 -------- 63943 -------- 65015 -------- 65840 -------- 66748 -------- 67584 -------- 68611 -------- 69729 -------- 70883 -------- 71725 -------- 72926 -------- 73924 -------- 74891 -------- 76176 -------- 77264 -------- 78405 -------- 79257 -------- 80310 -------- 81321 -------- 82270 -------- 83162 -------- 84049 -------- 85004 -------- 86255 -------- 87262 -------- 88259 -------- 89276 -------- 90374 -------- 91493 -------- 92454 -------- 93310 -------- 94246 -------- 95407 -------- 96295 -------- 97113 -------- 98069 -------- 98991 -------- 100116 ------- 100871 -------- 101805 -------- 102871 -------- 103776 ------- 104536 -------- 105497 -------- 106526 ------- 107293 -------- 108529 -------- 109518 -------- 110802 -------- 111761 -------- 113044 -------- 113923 -------- 115027 -------- 116119 ------- 116867 -------- 117681 -------- 118553 -------- 119501 -------- 120563 -------- 121563 -------- 122437 -------- 123400 -------- 124288 -------- 125209 -------- 126234 -------- 127465 -------- 128356 -------- 129458 -------- 130604 -------- 131668 ------- 132428 -------- 133365 -------- 134403 -------- 135446 ------- 136179 -------- 137262 -------- 138380 -------- 139242 -------- 140134 -------- 141190 -------- 142146 -------- 143244 -------- 144097 -------- 145011 -------- 145982 -------- 146981 -------- 148207 -------- 149115 -------- 150119 -------- 151183 -------- 152627 -------- 153735 -------- 154585 -------- 155535 -------- 156315 -------- 157258 -------- 158494 -------- 159570 -------- 160487 -------- 161464 -------- 162446 -------- 163673 -------- 164509 -------- 165550 -------- 166548 -------- 167495 -------- 168601 -------- 169889 -------- 170916 -------- 172026 -------- 173351 -------- 174278 -------- 175359 -------- 176720 -------- 177872 -------- 179135 -------- 180304 -------- 181217 -------- 182345 -------- 183194 -------- 184282 -------- 185142 -------- 186147 -------- 187099 -------- 188024 -------- 189029 -------- 189936 -------- 190977 -------- 192044 -------- 193012 -------- 193858 -------- 195011 -------- 195927 -------- 197043 -------- 198236 -------- 199104 -------- 199995 - │ │ │ │ │ histogram(22)= 0 7640 1.843e+05 8060 - │ │ │ │ │ <--- 'Brand#11' ----------- 'Brand#55' - │ │ │ │ │ histogram(24)= 0 4240 1.9186e+05 3900 - │ │ │ │ │ <--- 1 ------------- 50 - │ │ │ │ │ histogram(25)= 0 5460 1.8978e+05 4760 - │ │ │ │ │ <--- 'JUMBO BAG' ------------ 'WRAP PKG' - │ │ │ │ ├── key: (19) - │ │ │ │ └── fd: (19)-->(22,24,25) - │ │ │ └── filters - │ │ │ └── p_size:24 >= 1 [type=bool, outer=(24), constraints=(/24: [/1 - ]; tight)] - │ │ └── filters - │ │ ├── p_partkey:19 = l_partkey:2 [type=bool, outer=(2,19), constraints=(/2: (/NULL - ]; /19: (/NULL - ]), fd=(2)==(19), (19)==(2)] - │ │ └── ((((((p_brand:22 = 'Brand#12') AND (p_container:25 IN ('SM BOX', 'SM CASE', 'SM PACK', 'SM PKG'))) AND (l_quantity:5 >= 1.0)) AND (l_quantity:5 <= 11.0)) AND (p_size:24 <= 5)) OR (((((p_brand:22 = 'Brand#23') AND (p_container:25 IN ('MED BAG', 'MED BOX', 'MED PACK', 'MED PKG'))) AND (l_quantity:5 >= 10.0)) AND (l_quantity:5 <= 20.0)) AND (p_size:24 <= 10))) OR (((((p_brand:22 = 'Brand#34') AND (p_container:25 IN ('LG BOX', 'LG CASE', 'LG PACK', 'LG PKG'))) AND (l_quantity:5 >= 20.0)) AND (l_quantity:5 <= 30.0)) AND (p_size:24 <= 15)) [type=bool, outer=(5,22,24,25), constraints=(/5: [/1.0 - /30.0]; /22: [/'Brand#12' - /'Brand#12'] [/'Brand#23' - /'Brand#23'] [/'Brand#34' - /'Brand#34']; /24: (/NULL - /15]; /25: [/'LG BOX' - /'LG BOX'] [/'LG CASE' - /'LG CASE'] [/'LG PACK' - /'LG PACK'] [/'LG PKG' - /'LG PKG'] [/'MED BAG' - /'MED BAG'] [/'MED BOX' - /'MED BOX'] [/'MED PACK' - /'MED PACK'] [/'MED PKG' - /'MED PKG'] [/'SM BOX' - /'SM BOX'] [/'SM CASE' - /'SM CASE'] [/'SM PACK' - /'SM PACK'] [/'SM PKG' - /'SM PKG'])] + │ │ └── distinct-on + │ │ ├── save-table-name: q19_distinct_on_4 + │ │ ├── columns: l_orderkey:1(int!null) l_partkey:2(int!null) l_linenumber:4(int!null) l_quantity:5(float!null) l_extendedprice:6(float!null) l_discount:7(float!null) l_shipinstruct:14(char!null) l_shipmode:15(char!null) p_partkey:19(int!null) p_brand:22(char!null) p_size:24(int!null) p_container:25(char!null) + │ │ ├── grouping columns: l_orderkey:1(int!null) l_linenumber:4(int!null) p_partkey:19(int!null) + │ │ ├── stats: [rows=182.3692, distinct(1)=182.304, null(1)=0, distinct(2)=182.369, null(2)=0, distinct(4)=13.9999, null(4)=0, distinct(5)=182.369, null(5)=0, distinct(6)=182.369, null(6)=0, distinct(7)=182.369, null(7)=0, distinct(14)=182.369, null(14)=0, distinct(15)=182.369, null(15)=0, distinct(19)=163.44, null(19)=0, distinct(22)=182.369, null(22)=0, distinct(24)=182.369, null(24)=0, distinct(25)=182.369, null(25)=0, distinct(1,4,19)=182.369, null(1,4,19)=0] + │ │ ├── key: (1,4,19) + │ │ ├── fd: (2)==(19), (19)==(2), (1,4,19)-->(2,5-7,14,15,22,24,25) + │ │ ├── union-all + │ │ │ ├── save-table-name: q19_union_all_5 + │ │ │ ├── columns: l_orderkey:1(int!null) l_partkey:2(int!null) l_linenumber:4(int!null) l_quantity:5(float!null) l_extendedprice:6(float!null) l_discount:7(float!null) l_shipinstruct:14(char!null) l_shipmode:15(char!null) p_partkey:19(int!null) p_brand:22(char!null) p_size:24(int!null) p_container:25(char!null) + │ │ │ ├── left columns: l_orderkey:32(int) l_partkey:33(int) l_linenumber:35(int) l_quantity:36(float) l_extendedprice:37(float) l_discount:38(float) l_shipinstruct:45(char) l_shipmode:46(char) p_partkey:50(int) p_brand:53(char) p_size:55(int) p_container:56(char) + │ │ │ ├── right columns: l_orderkey:61(int) l_partkey:62(int) l_linenumber:64(int) l_quantity:65(float) l_extendedprice:66(float) l_discount:67(float) l_shipinstruct:74(char) l_shipmode:75(char) p_partkey:79(int) p_brand:82(char) p_size:84(int) p_container:85(char) + │ │ │ ├── stats: [rows=182.3692, distinct(1)=182.304, null(1)=0, distinct(2)=163.44, null(2)=0, distinct(4)=13.9999, null(4)=0, distinct(5)=16.3504, null(5)=0, distinct(6)=182.302, null(6)=0, distinct(7)=21.9927, null(7)=0, distinct(14)=2, null(14)=0, distinct(15)=4, null(15)=0, distinct(19)=163.44, null(19)=0, distinct(22)=3, null(22)=0, distinct(24)=21.6667, null(24)=0, distinct(25)=12, null(25)=0, distinct(1,4,19)=182.369, null(1,4,19)=0] + │ │ │ ├── fd: (2)==(19), (19)==(2) + │ │ │ ├── inner-join (lookup lineitem) + │ │ │ │ ├── save-table-name: q19_lookup_join_6 + │ │ │ │ ├── columns: l_orderkey:32(int!null) l_partkey:33(int!null) l_linenumber:35(int!null) l_quantity:36(float!null) l_extendedprice:37(float!null) l_discount:38(float!null) l_shipinstruct:45(char!null) l_shipmode:46(char!null) p_partkey:50(int!null) p_brand:53(char!null) p_size:55(int!null) p_container:56(char!null) + │ │ │ │ ├── key columns: [32 35] = [32 35] + │ │ │ │ ├── lookup columns are key + │ │ │ │ ├── stats: [rows=99.88038, distinct(32)=99.8241, null(32)=0, distinct(33)=80.9514, null(33)=0, distinct(35)=7, null(35)=0, distinct(36)=10.7949, null(36)=0, distinct(37)=99.823, null(37)=0, distinct(38)=10.9987, null(38)=0, distinct(45)=1, null(45)=0, distinct(46)=2, null(46)=0, distinct(50)=80.9514, null(50)=0, distinct(53)=1, null(53)=0, distinct(55)=5, null(55)=0, distinct(56)=4, null(56)=0, distinct(32,35,50)=99.8804, null(32,35,50)=0] + │ │ │ │ ├── key: (32,35) + │ │ │ │ ├── fd: ()-->(45,53), (32,35)-->(33,36-38,46), (50)-->(55,56), (33)==(50), (50)==(33) + │ │ │ │ ├── inner-join (lookup lineitem@l_pk) + │ │ │ │ │ ├── save-table-name: q19_lookup_join_7 + │ │ │ │ │ ├── columns: l_orderkey:32(int!null) l_partkey:33(int!null) l_linenumber:35(int!null) p_partkey:50(int!null) p_brand:53(char!null) p_size:55(int!null) p_container:56(char!null) + │ │ │ │ │ ├── key columns: [50] = [33] + │ │ │ │ │ ├── stats: [rows=2438.288, distinct(32)=2436.35, null(32)=0, distinct(33)=80.9514, null(33)=0, distinct(35)=7, null(35)=0, distinct(50)=80.9514, null(50)=0, distinct(53)=1, null(53)=0, distinct(55)=5, null(55)=0, distinct(56)=4, null(56)=0] + │ │ │ │ │ ├── key: (32,35) + │ │ │ │ │ ├── fd: ()-->(53), (50)-->(55,56), (32,35)-->(33), (33)==(50), (50)==(33) + │ │ │ │ │ ├── select + │ │ │ │ │ │ ├── save-table-name: q19_select_8 + │ │ │ │ │ │ ├── columns: p_partkey:50(int!null) p_brand:53(char!null) p_size:55(int!null) p_container:56(char!null) + │ │ │ │ │ │ ├── stats: [rows=80.95144, distinct(50)=80.9514, null(50)=0, distinct(53)=1, null(53)=0, distinct(55)=5, null(55)=0, distinct(56)=4, null(56)=0, distinct(53,55,56)=20, null(53,55,56)=0] + │ │ │ │ │ │ │ histogram(53)= 0 80.951 + │ │ │ │ │ │ │ <--- 'Brand#12' + │ │ │ │ │ │ │ histogram(55)= 0 16.968 47.988 15.996 + │ │ │ │ │ │ │ <---- 1 ----------- 5 -- + │ │ │ │ │ │ │ histogram(56)= 0 20.238 0 20.238 0 20.238 0 20.238 + │ │ │ │ │ │ │ <--- 'SM BOX' --- 'SM CASE' --- 'SM PACK' --- 'SM PKG' + │ │ │ │ │ │ ├── key: (50) + │ │ │ │ │ │ ├── fd: ()-->(53), (50)-->(55,56) + │ │ │ │ │ │ ├── scan part + │ │ │ │ │ │ │ ├── save-table-name: q19_scan_9 + │ │ │ │ │ │ │ ├── columns: p_partkey:50(int!null) p_brand:53(char!null) p_size:55(int!null) p_container:56(char!null) + │ │ │ │ │ │ │ ├── stats: [rows=200000, distinct(50)=199241, null(50)=0, distinct(53)=25, null(53)=0, distinct(55)=50, null(55)=0, distinct(56)=40, null(56)=0, distinct(53,55,56)=50000, null(53,55,56)=0] + │ │ │ │ │ │ │ │ histogram(50)= 0 3.9982 929.57 3.9982 1135.5 3.9982 923.58 3.9982 1036.5 3.9982 964.56 3.9982 953.56 3.9982 899.59 3.9982 1152.5 3.9982 1118.5 3.9982 1137.5 3.9982 1129.5 3.9982 1136.5 3.9982 983.55 3.9982 983.55 3.9982 1028.5 3.9982 1007.5 3.9982 1036.5 3.9982 884.59 3.9982 985.55 3.9982 970.55 3.9982 1036.5 3.9982 943.57 3.9982 1020.5 3.9982 1001.5 3.9982 1001.5 3.9982 954.56 3.9982 1036.5 3.9982 990.54 3.9982 928.57 3.9982 1010.5 3.9982 892.59 3.9982 960.56 3.9982 1059.5 3.9982 947.56 3.9982 906.58 3.9982 935.57 3.9982 860.6 3.9982 971.55 3.9982 1067.5 3.9982 994.54 3.9982 961.56 3.9982 943.57 3.9982 901.59 3.9982 972.55 3.9982 956.56 3.9982 1106.5 3.9982 1152.5 3.9982 967.55 3.9982 943.57 3.9982 916.58 3.9982 1076.5 3.9982 933.57 3.9982 1108.5 3.9982 1081.5 3.9982 975.55 3.9982 1021.5 3.9982 1034.5 3.9982 905.58 3.9982 902.58 3.9982 966.56 3.9982 1080.5 3.9982 927.57 3.9982 936.57 3.9982 1008.5 3.9982 1033.5 3.9982 903.58 3.9982 944.57 3.9982 908.58 3.9982 1008.5 3.9982 1059.5 3.9982 1079.5 3.9982 911.58 3.9982 1107.5 3.9982 992.54 3.9982 975.55 3.9982 1156.5 3.9982 1042.5 3.9982 1072.5 3.9982 916.58 3.9982 1022.5 3.9982 999.54 3.9982 966.56 3.9982 936.57 3.9982 934.57 3.9982 969.55 3.9982 1136.5 3.9982 997.54 3.9982 991.54 3.9982 1002.5 3.9982 1047.5 3.9982 1059.5 3.9982 972.55 3.9982 918.58 3.9982 959.56 3.9982 1083.5 3.9982 934.57 3.9982 900.59 3.9982 970.55 3.9982 952.56 3.9982 1063.5 3.9982 870.6 3.9982 958.56 3.9982 1029.5 3.9982 943.57 3.9982 872.6 3.9982 972.55 3.9982 1009.5 3.9982 875.6 3.9982 1127.5 3.9982 987.55 3.9982 1156.5 3.9982 971.55 3.9982 1155.5 3.9982 930.57 3.9982 1051.5 3.9982 1044.5 3.9982 867.6 3.9982 898.59 3.9982 926.57 3.9982 965.56 3.9982 1027.5 3.9982 993.54 3.9982 927.57 3.9982 973.55 3.9982 934.57 3.9982 951.56 3.9982 1007.5 3.9982 1124.5 3.9982 936.57 3.9982 1050.5 3.9982 1075.5 3.9982 1028.5 3.9982 872.6 3.9982 960.56 3.9982 1014.5 3.9982 1017.5 3.9982 860.6 3.9982 1039.5 3.9982 1059.5 3.9982 921.58 3.9982 936.57 3.9982 1024.5 3.9982 970.55 3.9982 1047.5 3.9982 917.58 3.9982 948.56 3.9982 978.55 3.9982 993.54 3.9982 1121.5 3.9982 944.57 3.9982 1005.5 3.9982 1037.5 3.9982 1261.4 3.9982 1062.5 3.9982 925.57 3.9982 976.55 3.9982 892.59 3.9982 972.55 3.9982 1135.5 3.9982 1044.5 3.9982 959.56 3.9982 990.54 3.9982 993.54 3.9982 1130.5 3.9982 919.58 3.9982 1025.5 3.9982 1001.5 3.9982 974.55 3.9982 1061.5 3.9982 1166.5 3.9982 1017.5 3.9982 1063.5 3.9982 1188.5 3.9982 964.56 3.9982 1047.5 3.9982 1210.4 3.9982 1087.5 3.9982 1151.5 3.9982 1096.5 3.9982 957.56 3.9982 1073.5 3.9982 925.57 3.9982 1051.5 3.9982 930.57 3.9982 1005.5 3.9982 977.55 3.9982 963.56 3.9982 1005.5 3.9982 954.56 3.9982 1025.5 3.9982 1039.5 3.9982 985.55 3.9982 923.58 3.9982 1087.5 3.9982 958.56 3.9982 1066.5 3.9982 1110.5 3.9982 934.57 3.9982 946.56 3.9982 + │ │ │ │ │ │ │ │ <---- 23 --------- 901 --------- 2150 -------- 3016 -------- 4093 -------- 5038 -------- 5962 -------- 6778 -------- 8056 -------- 9277 -------- 10530 -------- 11769 -------- 13020 -------- 14001 -------- 14982 -------- 16046 -------- 17072 -------- 18149 -------- 18935 -------- 19920 -------- 20876 -------- 21953 -------- 22859 -------- 23908 -------- 24923 -------- 25938 -------- 26865 -------- 27943 -------- 28938 -------- 29813 -------- 30844 -------- 31647 -------- 32585 -------- 33704 -------- 34617 -------- 35448 -------- 36338 ------- 37071 -------- 38029 -------- 39162 -------- 40163 -------- 41103 -------- 42008 -------- 42828 -------- 43789 -------- 44720 -------- 45920 -------- 47197 -------- 48149 -------- 49054 -------- 49906 -------- 51054 -------- 51940 -------- 53144 -------- 54301 -------- 55267 -------- 56318 -------- 57393 -------- 58223 -------- 59046 -------- 59995 -------- 61150 -------- 62024 -------- 62915 -------- 63943 -------- 65015 -------- 65840 -------- 66748 -------- 67584 -------- 68611 -------- 69729 -------- 70883 -------- 71725 -------- 72926 -------- 73924 -------- 74891 -------- 76176 -------- 77264 -------- 78405 -------- 79257 -------- 80310 -------- 81321 -------- 82270 -------- 83162 -------- 84049 -------- 85004 -------- 86255 -------- 87262 -------- 88259 -------- 89276 -------- 90374 -------- 91493 -------- 92454 -------- 93310 -------- 94246 -------- 95407 -------- 96295 -------- 97113 -------- 98069 -------- 98991 -------- 100116 ------- 100871 -------- 101805 -------- 102871 -------- 103776 ------- 104536 -------- 105497 -------- 106526 ------- 107293 -------- 108529 -------- 109518 -------- 110802 -------- 111761 -------- 113044 -------- 113923 -------- 115027 -------- 116119 ------- 116867 -------- 117681 -------- 118553 -------- 119501 -------- 120563 -------- 121563 -------- 122437 -------- 123400 -------- 124288 -------- 125209 -------- 126234 -------- 127465 -------- 128356 -------- 129458 -------- 130604 -------- 131668 ------- 132428 -------- 133365 -------- 134403 -------- 135446 ------- 136179 -------- 137262 -------- 138380 -------- 139242 -------- 140134 -------- 141190 -------- 142146 -------- 143244 -------- 144097 -------- 145011 -------- 145982 -------- 146981 -------- 148207 -------- 149115 -------- 150119 -------- 151183 -------- 152627 -------- 153735 -------- 154585 -------- 155535 -------- 156315 -------- 157258 -------- 158494 -------- 159570 -------- 160487 -------- 161464 -------- 162446 -------- 163673 -------- 164509 -------- 165550 -------- 166548 -------- 167495 -------- 168601 -------- 169889 -------- 170916 -------- 172026 -------- 173351 -------- 174278 -------- 175359 -------- 176720 -------- 177872 -------- 179135 -------- 180304 -------- 181217 -------- 182345 -------- 183194 -------- 184282 -------- 185142 -------- 186147 -------- 187099 -------- 188024 -------- 189029 -------- 189936 -------- 190977 -------- 192044 -------- 193012 -------- 193858 -------- 195011 -------- 195927 -------- 197043 -------- 198236 -------- 199104 -------- 199995 + │ │ │ │ │ │ │ │ histogram(53)= 0 7640 1.843e+05 8060 + │ │ │ │ │ │ │ │ <--- 'Brand#11' ----------- 'Brand#55' + │ │ │ │ │ │ │ │ histogram(55)= 0 4240 1.9186e+05 3900 + │ │ │ │ │ │ │ │ <--- 1 ------------- 50 + │ │ │ │ │ │ │ │ histogram(56)= 0 5460 1.8978e+05 4760 + │ │ │ │ │ │ │ │ <--- 'JUMBO BAG' ------------ 'WRAP PKG' + │ │ │ │ │ │ │ ├── key: (50) + │ │ │ │ │ │ │ └── fd: (50)-->(53,55,56) + │ │ │ │ │ │ └── filters + │ │ │ │ │ │ ├── (p_size:55 >= 1) AND (p_size:55 <= 5) [type=bool, outer=(55), constraints=(/55: [/1 - /5]; tight)] + │ │ │ │ │ │ ├── p_brand:53 = 'Brand#12' [type=bool, outer=(53), constraints=(/53: [/'Brand#12' - /'Brand#12']; tight), fd=()-->(53)] + │ │ │ │ │ │ └── p_container:56 IN ('SM BOX', 'SM CASE', 'SM PACK', 'SM PKG') [type=bool, outer=(56), constraints=(/56: [/'SM BOX' - /'SM BOX'] [/'SM CASE' - /'SM CASE'] [/'SM PACK' - /'SM PACK'] [/'SM PKG' - /'SM PKG']; tight)] + │ │ │ │ │ └── filters (true) + │ │ │ │ └── filters + │ │ │ │ ├── (l_quantity:36 >= 1.0) AND (l_quantity:36 <= 11.0) [type=bool, outer=(36), constraints=(/36: [/1.0 - /11.0]; tight)] + │ │ │ │ ├── l_shipmode:46 IN ('AIR', 'AIR REG') [type=bool, outer=(46), constraints=(/46: [/'AIR' - /'AIR'] [/'AIR REG' - /'AIR REG']; tight)] + │ │ │ │ └── l_shipinstruct:45 = 'DELIVER IN PERSON' [type=bool, outer=(45), constraints=(/45: [/'DELIVER IN PERSON' - /'DELIVER IN PERSON']; tight), fd=()-->(45)] + │ │ │ └── project + │ │ │ ├── save-table-name: q19_project_10 + │ │ │ ├── columns: l_orderkey:61(int!null) l_partkey:62(int!null) l_linenumber:64(int!null) l_quantity:65(float!null) l_extendedprice:66(float!null) l_discount:67(float!null) l_shipinstruct:74(char!null) l_shipmode:75(char!null) p_partkey:79(int!null) p_brand:82(char!null) p_size:84(int!null) p_container:85(char!null) + │ │ │ ├── stats: [rows=82.48887, distinct(61)=82.4798, null(61)=0, distinct(62)=82.4889, null(62)=0, distinct(64)=6.99995, null(64)=0, distinct(65)=5.55556, null(65)=0, distinct(66)=82.479, null(66)=0, distinct(67)=10.9939, null(67)=0, distinct(74)=1, null(74)=0, distinct(75)=2, null(75)=0, distinct(79)=82.4889, null(79)=0, distinct(82)=2, null(82)=0, distinct(84)=16.6667, null(84)=0, distinct(85)=8, null(85)=0, distinct(61,64,79)=82.4889, null(61,64,79)=0, distinct(82,84,85)=82.4889, null(82,84,85)=0] + │ │ │ ├── key: (61,64) + │ │ │ ├── fd: ()-->(74), (61,64)-->(62,65-67,75), (79)-->(82,84,85), (62)==(79), (79)==(62) + │ │ │ └── distinct-on + │ │ │ ├── save-table-name: q19_distinct_on_11 + │ │ │ ├── columns: l_orderkey:61(int!null) l_partkey:62(int!null) l_linenumber:64(int!null) l_quantity:65(float!null) l_extendedprice:66(float!null) l_discount:67(float!null) l_shipinstruct:74(char!null) l_shipmode:75(char!null) p_partkey:79(int!null) p_brand:82(char!null) p_size:84(int!null) p_container:85(char!null) + │ │ │ ├── grouping columns: l_orderkey:61(int!null) l_linenumber:64(int!null) p_partkey:79(int!null) + │ │ │ ├── stats: [rows=486.9996, distinct(61)=486.233, null(61)=0, distinct(62)=487, null(62)=0, distinct(64)=14, null(64)=0, distinct(65)=487, null(65)=0, distinct(66)=487, null(66)=0, distinct(67)=487, null(67)=0, distinct(74)=487, null(74)=0, distinct(75)=487, null(75)=0, distinct(79)=401.84, null(79)=0, distinct(82)=487, null(82)=0, distinct(84)=487, null(84)=0, distinct(85)=487, null(85)=0, distinct(61,64,79)=487, null(61,64,79)=0] + │ │ │ ├── key: (61,64,79) + │ │ │ ├── fd: (62)==(79), (79)==(62), (61,64,79)-->(62,65-67,74,75,82,84,85) + │ │ │ ├── union-all + │ │ │ │ ├── save-table-name: q19_union_all_12 + │ │ │ │ ├── columns: l_orderkey:61(int!null) l_partkey:62(int!null) l_linenumber:64(int!null) l_quantity:65(float!null) l_extendedprice:66(float!null) l_discount:67(float!null) l_shipinstruct:74(char!null) l_shipmode:75(char!null) p_partkey:79(int!null) p_brand:82(char!null) p_size:84(int!null) p_container:85(char!null) + │ │ │ │ ├── left columns: l_orderkey:90(int) l_partkey:91(int) l_linenumber:93(int) l_quantity:94(float) l_extendedprice:95(float) l_discount:96(float) l_shipinstruct:103(char) l_shipmode:104(char) p_partkey:108(int) p_brand:111(char) p_size:113(int) p_container:114(char) + │ │ │ │ ├── right columns: l_orderkey:119(int) l_partkey:120(int) l_linenumber:122(int) l_quantity:123(float) l_extendedprice:124(float) l_discount:125(float) l_shipinstruct:132(char) l_shipmode:133(char) p_partkey:137(int) p_brand:140(char) p_size:142(int) p_container:143(char) + │ │ │ │ ├── stats: [rows=486.9996, distinct(61)=486.233, null(61)=0, distinct(62)=401.84, null(62)=0, distinct(64)=14, null(64)=0, distinct(65)=19.5918, null(65)=0, distinct(66)=486.22, null(66)=0, distinct(67)=22, null(67)=0, distinct(74)=2, null(74)=0, distinct(75)=4, null(75)=0, distinct(79)=401.84, null(79)=0, distinct(82)=2, null(82)=0, distinct(84)=25, null(84)=0, distinct(85)=8, null(85)=0, distinct(61,64,79)=487, null(61,64,79)=0] + │ │ │ │ ├── fd: (62)==(79), (79)==(62) + │ │ │ │ ├── inner-join (lookup lineitem) + │ │ │ │ │ ├── save-table-name: q19_lookup_join_13 + │ │ │ │ │ ├── columns: l_orderkey:90(int!null) l_partkey:91(int!null) l_linenumber:93(int!null) l_quantity:94(float!null) l_extendedprice:95(float!null) l_discount:96(float!null) l_shipinstruct:103(char!null) l_shipmode:104(char!null) p_partkey:108(int!null) p_brand:111(char!null) p_size:113(int!null) p_container:114(char!null) + │ │ │ │ │ ├── key columns: [90 93] = [90 93] + │ │ │ │ │ ├── lookup columns are key + │ │ │ │ │ ├── stats: [rows=291.9642, distinct(90)=291.434, null(90)=0, distinct(91)=240.909, null(91)=0, distinct(93)=7, null(93)=0, distinct(94)=9.79592, null(94)=0, distinct(95)=291.425, null(95)=0, distinct(96)=11, null(96)=0, distinct(103)=1, null(103)=0, distinct(104)=2, null(104)=0, distinct(108)=240.909, null(108)=0, distinct(111)=1, null(111)=0, distinct(113)=15, null(113)=0, distinct(114)=4, null(114)=0, distinct(90,93,108)=291.964, null(90,93,108)=0] + │ │ │ │ │ ├── key: (90,93) + │ │ │ │ │ ├── fd: ()-->(103,111), (90,93)-->(91,94-96,104), (108)-->(113,114), (91)==(108), (108)==(91) + │ │ │ │ │ ├── inner-join (lookup lineitem@l_pk) + │ │ │ │ │ │ ├── save-table-name: q19_lookup_join_14 + │ │ │ │ │ │ ├── columns: l_orderkey:90(int!null) l_partkey:91(int!null) l_linenumber:93(int!null) p_partkey:108(int!null) p_brand:111(char!null) p_size:113(int!null) p_container:114(char!null) + │ │ │ │ │ │ ├── key columns: [108] = [91] + │ │ │ │ │ │ ├── stats: [rows=7256.302, distinct(90)=7239.11, null(90)=0, distinct(91)=240.909, null(91)=0, distinct(93)=7, null(93)=0, distinct(108)=240.909, null(108)=0, distinct(111)=1, null(111)=0, distinct(113)=15, null(113)=0, distinct(114)=4, null(114)=0] + │ │ │ │ │ │ ├── key: (90,93) + │ │ │ │ │ │ ├── fd: ()-->(111), (108)-->(113,114), (90,93)-->(91), (91)==(108), (108)==(91) + │ │ │ │ │ │ ├── select + │ │ │ │ │ │ │ ├── save-table-name: q19_select_15 + │ │ │ │ │ │ │ ├── columns: p_partkey:108(int!null) p_brand:111(char!null) p_size:113(int!null) p_container:114(char!null) + │ │ │ │ │ │ │ ├── stats: [rows=240.91, distinct(108)=240.909, null(108)=0, distinct(111)=1, null(111)=0, distinct(113)=15, null(113)=0, distinct(114)=4, null(114)=0, distinct(111,113,114)=60, null(111,113,114)=0] + │ │ │ │ │ │ │ │ histogram(111)= 0 240.91 + │ │ │ │ │ │ │ │ <--- 'Brand#34' + │ │ │ │ │ │ │ │ histogram(113)= 0 16.968 207.95 15.996 + │ │ │ │ │ │ │ │ <---- 1 ----------- 15 - + │ │ │ │ │ │ │ │ histogram(114)= 0 60.228 0 60.228 0 60.228 0 60.228 + │ │ │ │ │ │ │ │ <--- 'LG BOX' --- 'LG CASE' --- 'LG PACK' --- 'LG PKG' + │ │ │ │ │ │ │ ├── key: (108) + │ │ │ │ │ │ │ ├── fd: ()-->(111), (108)-->(113,114) + │ │ │ │ │ │ │ ├── scan part + │ │ │ │ │ │ │ │ ├── save-table-name: q19_scan_16 + │ │ │ │ │ │ │ │ ├── columns: p_partkey:108(int!null) p_brand:111(char!null) p_size:113(int!null) p_container:114(char!null) + │ │ │ │ │ │ │ │ ├── stats: [rows=200000, distinct(108)=199241, null(108)=0, distinct(111)=25, null(111)=0, distinct(113)=50, null(113)=0, distinct(114)=40, null(114)=0, distinct(111,113,114)=50000, null(111,113,114)=0] + │ │ │ │ │ │ │ │ │ histogram(108)= 0 3.9982 929.57 3.9982 1135.5 3.9982 923.58 3.9982 1036.5 3.9982 964.56 3.9982 953.56 3.9982 899.59 3.9982 1152.5 3.9982 1118.5 3.9982 1137.5 3.9982 1129.5 3.9982 1136.5 3.9982 983.55 3.9982 983.55 3.9982 1028.5 3.9982 1007.5 3.9982 1036.5 3.9982 884.59 3.9982 985.55 3.9982 970.55 3.9982 1036.5 3.9982 943.57 3.9982 1020.5 3.9982 1001.5 3.9982 1001.5 3.9982 954.56 3.9982 1036.5 3.9982 990.54 3.9982 928.57 3.9982 1010.5 3.9982 892.59 3.9982 960.56 3.9982 1059.5 3.9982 947.56 3.9982 906.58 3.9982 935.57 3.9982 860.6 3.9982 971.55 3.9982 1067.5 3.9982 994.54 3.9982 961.56 3.9982 943.57 3.9982 901.59 3.9982 972.55 3.9982 956.56 3.9982 1106.5 3.9982 1152.5 3.9982 967.55 3.9982 943.57 3.9982 916.58 3.9982 1076.5 3.9982 933.57 3.9982 1108.5 3.9982 1081.5 3.9982 975.55 3.9982 1021.5 3.9982 1034.5 3.9982 905.58 3.9982 902.58 3.9982 966.56 3.9982 1080.5 3.9982 927.57 3.9982 936.57 3.9982 1008.5 3.9982 1033.5 3.9982 903.58 3.9982 944.57 3.9982 908.58 3.9982 1008.5 3.9982 1059.5 3.9982 1079.5 3.9982 911.58 3.9982 1107.5 3.9982 992.54 3.9982 975.55 3.9982 1156.5 3.9982 1042.5 3.9982 1072.5 3.9982 916.58 3.9982 1022.5 3.9982 999.54 3.9982 966.56 3.9982 936.57 3.9982 934.57 3.9982 969.55 3.9982 1136.5 3.9982 997.54 3.9982 991.54 3.9982 1002.5 3.9982 1047.5 3.9982 1059.5 3.9982 972.55 3.9982 918.58 3.9982 959.56 3.9982 1083.5 3.9982 934.57 3.9982 900.59 3.9982 970.55 3.9982 952.56 3.9982 1063.5 3.9982 870.6 3.9982 958.56 3.9982 1029.5 3.9982 943.57 3.9982 872.6 3.9982 972.55 3.9982 1009.5 3.9982 875.6 3.9982 1127.5 3.9982 987.55 3.9982 1156.5 3.9982 971.55 3.9982 1155.5 3.9982 930.57 3.9982 1051.5 3.9982 1044.5 3.9982 867.6 3.9982 898.59 3.9982 926.57 3.9982 965.56 3.9982 1027.5 3.9982 993.54 3.9982 927.57 3.9982 973.55 3.9982 934.57 3.9982 951.56 3.9982 1007.5 3.9982 1124.5 3.9982 936.57 3.9982 1050.5 3.9982 1075.5 3.9982 1028.5 3.9982 872.6 3.9982 960.56 3.9982 1014.5 3.9982 1017.5 3.9982 860.6 3.9982 1039.5 3.9982 1059.5 3.9982 921.58 3.9982 936.57 3.9982 1024.5 3.9982 970.55 3.9982 1047.5 3.9982 917.58 3.9982 948.56 3.9982 978.55 3.9982 993.54 3.9982 1121.5 3.9982 944.57 3.9982 1005.5 3.9982 1037.5 3.9982 1261.4 3.9982 1062.5 3.9982 925.57 3.9982 976.55 3.9982 892.59 3.9982 972.55 3.9982 1135.5 3.9982 1044.5 3.9982 959.56 3.9982 990.54 3.9982 993.54 3.9982 1130.5 3.9982 919.58 3.9982 1025.5 3.9982 1001.5 3.9982 974.55 3.9982 1061.5 3.9982 1166.5 3.9982 1017.5 3.9982 1063.5 3.9982 1188.5 3.9982 964.56 3.9982 1047.5 3.9982 1210.4 3.9982 1087.5 3.9982 1151.5 3.9982 1096.5 3.9982 957.56 3.9982 1073.5 3.9982 925.57 3.9982 1051.5 3.9982 930.57 3.9982 1005.5 3.9982 977.55 3.9982 963.56 3.9982 1005.5 3.9982 954.56 3.9982 1025.5 3.9982 1039.5 3.9982 985.55 3.9982 923.58 3.9982 1087.5 3.9982 958.56 3.9982 1066.5 3.9982 1110.5 3.9982 934.57 3.9982 946.56 3.9982 + │ │ │ │ │ │ │ │ │ <---- 23 --------- 901 --------- 2150 -------- 3016 -------- 4093 -------- 5038 -------- 5962 -------- 6778 -------- 8056 -------- 9277 -------- 10530 -------- 11769 -------- 13020 -------- 14001 -------- 14982 -------- 16046 -------- 17072 -------- 18149 -------- 18935 -------- 19920 -------- 20876 -------- 21953 -------- 22859 -------- 23908 -------- 24923 -------- 25938 -------- 26865 -------- 27943 -------- 28938 -------- 29813 -------- 30844 -------- 31647 -------- 32585 -------- 33704 -------- 34617 -------- 35448 -------- 36338 ------- 37071 -------- 38029 -------- 39162 -------- 40163 -------- 41103 -------- 42008 -------- 42828 -------- 43789 -------- 44720 -------- 45920 -------- 47197 -------- 48149 -------- 49054 -------- 49906 -------- 51054 -------- 51940 -------- 53144 -------- 54301 -------- 55267 -------- 56318 -------- 57393 -------- 58223 -------- 59046 -------- 59995 -------- 61150 -------- 62024 -------- 62915 -------- 63943 -------- 65015 -------- 65840 -------- 66748 -------- 67584 -------- 68611 -------- 69729 -------- 70883 -------- 71725 -------- 72926 -------- 73924 -------- 74891 -------- 76176 -------- 77264 -------- 78405 -------- 79257 -------- 80310 -------- 81321 -------- 82270 -------- 83162 -------- 84049 -------- 85004 -------- 86255 -------- 87262 -------- 88259 -------- 89276 -------- 90374 -------- 91493 -------- 92454 -------- 93310 -------- 94246 -------- 95407 -------- 96295 -------- 97113 -------- 98069 -------- 98991 -------- 100116 ------- 100871 -------- 101805 -------- 102871 -------- 103776 ------- 104536 -------- 105497 -------- 106526 ------- 107293 -------- 108529 -------- 109518 -------- 110802 -------- 111761 -------- 113044 -------- 113923 -------- 115027 -------- 116119 ------- 116867 -------- 117681 -------- 118553 -------- 119501 -------- 120563 -------- 121563 -------- 122437 -------- 123400 -------- 124288 -------- 125209 -------- 126234 -------- 127465 -------- 128356 -------- 129458 -------- 130604 -------- 131668 ------- 132428 -------- 133365 -------- 134403 -------- 135446 ------- 136179 -------- 137262 -------- 138380 -------- 139242 -------- 140134 -------- 141190 -------- 142146 -------- 143244 -------- 144097 -------- 145011 -------- 145982 -------- 146981 -------- 148207 -------- 149115 -------- 150119 -------- 151183 -------- 152627 -------- 153735 -------- 154585 -------- 155535 -------- 156315 -------- 157258 -------- 158494 -------- 159570 -------- 160487 -------- 161464 -------- 162446 -------- 163673 -------- 164509 -------- 165550 -------- 166548 -------- 167495 -------- 168601 -------- 169889 -------- 170916 -------- 172026 -------- 173351 -------- 174278 -------- 175359 -------- 176720 -------- 177872 -------- 179135 -------- 180304 -------- 181217 -------- 182345 -------- 183194 -------- 184282 -------- 185142 -------- 186147 -------- 187099 -------- 188024 -------- 189029 -------- 189936 -------- 190977 -------- 192044 -------- 193012 -------- 193858 -------- 195011 -------- 195927 -------- 197043 -------- 198236 -------- 199104 -------- 199995 + │ │ │ │ │ │ │ │ │ histogram(111)= 0 7640 1.843e+05 8060 + │ │ │ │ │ │ │ │ │ <--- 'Brand#11' ----------- 'Brand#55' + │ │ │ │ │ │ │ │ │ histogram(113)= 0 4240 1.9186e+05 3900 + │ │ │ │ │ │ │ │ │ <--- 1 ------------- 50 + │ │ │ │ │ │ │ │ │ histogram(114)= 0 5460 1.8978e+05 4760 + │ │ │ │ │ │ │ │ │ <--- 'JUMBO BAG' ------------ 'WRAP PKG' + │ │ │ │ │ │ │ │ ├── key: (108) + │ │ │ │ │ │ │ │ └── fd: (108)-->(111,113,114) + │ │ │ │ │ │ │ └── filters + │ │ │ │ │ │ │ ├── (p_size:113 >= 1) AND (p_size:113 <= 15) [type=bool, outer=(113), constraints=(/113: [/1 - /15]; tight)] + │ │ │ │ │ │ │ ├── p_brand:111 = 'Brand#34' [type=bool, outer=(111), constraints=(/111: [/'Brand#34' - /'Brand#34']; tight), fd=()-->(111)] + │ │ │ │ │ │ │ └── p_container:114 IN ('LG BOX', 'LG CASE', 'LG PACK', 'LG PKG') [type=bool, outer=(114), constraints=(/114: [/'LG BOX' - /'LG BOX'] [/'LG CASE' - /'LG CASE'] [/'LG PACK' - /'LG PACK'] [/'LG PKG' - /'LG PKG']; tight)] + │ │ │ │ │ │ └── filters (true) + │ │ │ │ │ └── filters + │ │ │ │ │ ├── (l_quantity:94 >= 20.0) AND (l_quantity:94 <= 30.0) [type=bool, outer=(94), constraints=(/94: [/20.0 - /30.0]; tight)] + │ │ │ │ │ ├── l_shipmode:104 IN ('AIR', 'AIR REG') [type=bool, outer=(104), constraints=(/104: [/'AIR' - /'AIR'] [/'AIR REG' - /'AIR REG']; tight)] + │ │ │ │ │ └── l_shipinstruct:103 = 'DELIVER IN PERSON' [type=bool, outer=(103), constraints=(/103: [/'DELIVER IN PERSON' - /'DELIVER IN PERSON']; tight), fd=()-->(103)] + │ │ │ │ └── inner-join (lookup lineitem) + │ │ │ │ ├── save-table-name: q19_lookup_join_17 + │ │ │ │ ├── columns: l_orderkey:119(int!null) l_partkey:120(int!null) l_linenumber:122(int!null) l_quantity:123(float!null) l_extendedprice:124(float!null) l_discount:125(float!null) l_shipinstruct:132(char!null) l_shipmode:133(char!null) p_partkey:137(int!null) p_brand:140(char!null) p_size:142(int!null) p_container:143(char!null) + │ │ │ │ ├── key columns: [119 122] = [119 122] + │ │ │ │ ├── lookup columns are key + │ │ │ │ ├── stats: [rows=195.0355, distinct(119)=194.799, null(119)=0, distinct(120)=160.93, null(120)=0, distinct(122)=7, null(122)=0, distinct(123)=9.79592, null(123)=0, distinct(124)=194.795, null(124)=0, distinct(125)=11, null(125)=0, distinct(132)=1, null(132)=0, distinct(133)=2, null(133)=0, distinct(137)=160.93, null(137)=0, distinct(140)=1, null(140)=0, distinct(142)=10, null(142)=0, distinct(143)=4, null(143)=0, distinct(119,122,137)=195.035, null(119,122,137)=0] + │ │ │ │ ├── key: (119,122) + │ │ │ │ ├── fd: ()-->(132,140), (119,122)-->(120,123-125,133), (137)-->(142,143), (120)==(137), (137)==(120) + │ │ │ │ ├── inner-join (lookup lineitem@l_pk) + │ │ │ │ │ ├── save-table-name: q19_lookup_join_18 + │ │ │ │ │ ├── columns: l_orderkey:119(int!null) l_partkey:120(int!null) l_linenumber:122(int!null) p_partkey:137(int!null) p_brand:140(char!null) p_size:142(int!null) p_container:143(char!null) + │ │ │ │ │ ├── key columns: [137] = [120] + │ │ │ │ │ ├── stats: [rows=4847.295, distinct(119)=4839.62, null(119)=0, distinct(120)=160.93, null(120)=0, distinct(122)=7, null(122)=0, distinct(137)=160.93, null(137)=0, distinct(140)=1, null(140)=0, distinct(142)=10, null(142)=0, distinct(143)=4, null(143)=0] + │ │ │ │ │ ├── key: (119,122) + │ │ │ │ │ ├── fd: ()-->(140), (137)-->(142,143), (119,122)-->(120), (120)==(137), (137)==(120) + │ │ │ │ │ ├── select + │ │ │ │ │ │ ├── save-table-name: q19_select_19 + │ │ │ │ │ │ ├── columns: p_partkey:137(int!null) p_brand:140(char!null) p_size:142(int!null) p_container:143(char!null) + │ │ │ │ │ │ ├── stats: [rows=160.9307, distinct(137)=160.93, null(137)=0, distinct(140)=1, null(140)=0, distinct(142)=10, null(142)=0, distinct(143)=4, null(143)=0, distinct(140,142,143)=40, null(140,142,143)=0] + │ │ │ │ │ │ │ histogram(140)= 0 160.93 + │ │ │ │ │ │ │ <--- 'Brand#23' + │ │ │ │ │ │ │ histogram(142)= 0 16.968 127.97 15.996 + │ │ │ │ │ │ │ <---- 1 ----------- 10 - + │ │ │ │ │ │ │ histogram(143)= 0 40.233 0 40.233 0 40.233 0 40.233 + │ │ │ │ │ │ │ <--- 'MED BAG' --- 'MED BOX' --- 'MED PACK' --- 'MED PKG' + │ │ │ │ │ │ ├── key: (137) + │ │ │ │ │ │ ├── fd: ()-->(140), (137)-->(142,143) + │ │ │ │ │ │ ├── scan part + │ │ │ │ │ │ │ ├── save-table-name: q19_scan_20 + │ │ │ │ │ │ │ ├── columns: p_partkey:137(int!null) p_brand:140(char!null) p_size:142(int!null) p_container:143(char!null) + │ │ │ │ │ │ │ ├── stats: [rows=200000, distinct(137)=199241, null(137)=0, distinct(140)=25, null(140)=0, distinct(142)=50, null(142)=0, distinct(143)=40, null(143)=0, distinct(140,142,143)=50000, null(140,142,143)=0] + │ │ │ │ │ │ │ │ histogram(137)= 0 3.9982 929.57 3.9982 1135.5 3.9982 923.58 3.9982 1036.5 3.9982 964.56 3.9982 953.56 3.9982 899.59 3.9982 1152.5 3.9982 1118.5 3.9982 1137.5 3.9982 1129.5 3.9982 1136.5 3.9982 983.55 3.9982 983.55 3.9982 1028.5 3.9982 1007.5 3.9982 1036.5 3.9982 884.59 3.9982 985.55 3.9982 970.55 3.9982 1036.5 3.9982 943.57 3.9982 1020.5 3.9982 1001.5 3.9982 1001.5 3.9982 954.56 3.9982 1036.5 3.9982 990.54 3.9982 928.57 3.9982 1010.5 3.9982 892.59 3.9982 960.56 3.9982 1059.5 3.9982 947.56 3.9982 906.58 3.9982 935.57 3.9982 860.6 3.9982 971.55 3.9982 1067.5 3.9982 994.54 3.9982 961.56 3.9982 943.57 3.9982 901.59 3.9982 972.55 3.9982 956.56 3.9982 1106.5 3.9982 1152.5 3.9982 967.55 3.9982 943.57 3.9982 916.58 3.9982 1076.5 3.9982 933.57 3.9982 1108.5 3.9982 1081.5 3.9982 975.55 3.9982 1021.5 3.9982 1034.5 3.9982 905.58 3.9982 902.58 3.9982 966.56 3.9982 1080.5 3.9982 927.57 3.9982 936.57 3.9982 1008.5 3.9982 1033.5 3.9982 903.58 3.9982 944.57 3.9982 908.58 3.9982 1008.5 3.9982 1059.5 3.9982 1079.5 3.9982 911.58 3.9982 1107.5 3.9982 992.54 3.9982 975.55 3.9982 1156.5 3.9982 1042.5 3.9982 1072.5 3.9982 916.58 3.9982 1022.5 3.9982 999.54 3.9982 966.56 3.9982 936.57 3.9982 934.57 3.9982 969.55 3.9982 1136.5 3.9982 997.54 3.9982 991.54 3.9982 1002.5 3.9982 1047.5 3.9982 1059.5 3.9982 972.55 3.9982 918.58 3.9982 959.56 3.9982 1083.5 3.9982 934.57 3.9982 900.59 3.9982 970.55 3.9982 952.56 3.9982 1063.5 3.9982 870.6 3.9982 958.56 3.9982 1029.5 3.9982 943.57 3.9982 872.6 3.9982 972.55 3.9982 1009.5 3.9982 875.6 3.9982 1127.5 3.9982 987.55 3.9982 1156.5 3.9982 971.55 3.9982 1155.5 3.9982 930.57 3.9982 1051.5 3.9982 1044.5 3.9982 867.6 3.9982 898.59 3.9982 926.57 3.9982 965.56 3.9982 1027.5 3.9982 993.54 3.9982 927.57 3.9982 973.55 3.9982 934.57 3.9982 951.56 3.9982 1007.5 3.9982 1124.5 3.9982 936.57 3.9982 1050.5 3.9982 1075.5 3.9982 1028.5 3.9982 872.6 3.9982 960.56 3.9982 1014.5 3.9982 1017.5 3.9982 860.6 3.9982 1039.5 3.9982 1059.5 3.9982 921.58 3.9982 936.57 3.9982 1024.5 3.9982 970.55 3.9982 1047.5 3.9982 917.58 3.9982 948.56 3.9982 978.55 3.9982 993.54 3.9982 1121.5 3.9982 944.57 3.9982 1005.5 3.9982 1037.5 3.9982 1261.4 3.9982 1062.5 3.9982 925.57 3.9982 976.55 3.9982 892.59 3.9982 972.55 3.9982 1135.5 3.9982 1044.5 3.9982 959.56 3.9982 990.54 3.9982 993.54 3.9982 1130.5 3.9982 919.58 3.9982 1025.5 3.9982 1001.5 3.9982 974.55 3.9982 1061.5 3.9982 1166.5 3.9982 1017.5 3.9982 1063.5 3.9982 1188.5 3.9982 964.56 3.9982 1047.5 3.9982 1210.4 3.9982 1087.5 3.9982 1151.5 3.9982 1096.5 3.9982 957.56 3.9982 1073.5 3.9982 925.57 3.9982 1051.5 3.9982 930.57 3.9982 1005.5 3.9982 977.55 3.9982 963.56 3.9982 1005.5 3.9982 954.56 3.9982 1025.5 3.9982 1039.5 3.9982 985.55 3.9982 923.58 3.9982 1087.5 3.9982 958.56 3.9982 1066.5 3.9982 1110.5 3.9982 934.57 3.9982 946.56 3.9982 + │ │ │ │ │ │ │ │ <---- 23 --------- 901 --------- 2150 -------- 3016 -------- 4093 -------- 5038 -------- 5962 -------- 6778 -------- 8056 -------- 9277 -------- 10530 -------- 11769 -------- 13020 -------- 14001 -------- 14982 -------- 16046 -------- 17072 -------- 18149 -------- 18935 -------- 19920 -------- 20876 -------- 21953 -------- 22859 -------- 23908 -------- 24923 -------- 25938 -------- 26865 -------- 27943 -------- 28938 -------- 29813 -------- 30844 -------- 31647 -------- 32585 -------- 33704 -------- 34617 -------- 35448 -------- 36338 ------- 37071 -------- 38029 -------- 39162 -------- 40163 -------- 41103 -------- 42008 -------- 42828 -------- 43789 -------- 44720 -------- 45920 -------- 47197 -------- 48149 -------- 49054 -------- 49906 -------- 51054 -------- 51940 -------- 53144 -------- 54301 -------- 55267 -------- 56318 -------- 57393 -------- 58223 -------- 59046 -------- 59995 -------- 61150 -------- 62024 -------- 62915 -------- 63943 -------- 65015 -------- 65840 -------- 66748 -------- 67584 -------- 68611 -------- 69729 -------- 70883 -------- 71725 -------- 72926 -------- 73924 -------- 74891 -------- 76176 -------- 77264 -------- 78405 -------- 79257 -------- 80310 -------- 81321 -------- 82270 -------- 83162 -------- 84049 -------- 85004 -------- 86255 -------- 87262 -------- 88259 -------- 89276 -------- 90374 -------- 91493 -------- 92454 -------- 93310 -------- 94246 -------- 95407 -------- 96295 -------- 97113 -------- 98069 -------- 98991 -------- 100116 ------- 100871 -------- 101805 -------- 102871 -------- 103776 ------- 104536 -------- 105497 -------- 106526 ------- 107293 -------- 108529 -------- 109518 -------- 110802 -------- 111761 -------- 113044 -------- 113923 -------- 115027 -------- 116119 ------- 116867 -------- 117681 -------- 118553 -------- 119501 -------- 120563 -------- 121563 -------- 122437 -------- 123400 -------- 124288 -------- 125209 -------- 126234 -------- 127465 -------- 128356 -------- 129458 -------- 130604 -------- 131668 ------- 132428 -------- 133365 -------- 134403 -------- 135446 ------- 136179 -------- 137262 -------- 138380 -------- 139242 -------- 140134 -------- 141190 -------- 142146 -------- 143244 -------- 144097 -------- 145011 -------- 145982 -------- 146981 -------- 148207 -------- 149115 -------- 150119 -------- 151183 -------- 152627 -------- 153735 -------- 154585 -------- 155535 -------- 156315 -------- 157258 -------- 158494 -------- 159570 -------- 160487 -------- 161464 -------- 162446 -------- 163673 -------- 164509 -------- 165550 -------- 166548 -------- 167495 -------- 168601 -------- 169889 -------- 170916 -------- 172026 -------- 173351 -------- 174278 -------- 175359 -------- 176720 -------- 177872 -------- 179135 -------- 180304 -------- 181217 -------- 182345 -------- 183194 -------- 184282 -------- 185142 -------- 186147 -------- 187099 -------- 188024 -------- 189029 -------- 189936 -------- 190977 -------- 192044 -------- 193012 -------- 193858 -------- 195011 -------- 195927 -------- 197043 -------- 198236 -------- 199104 -------- 199995 + │ │ │ │ │ │ │ │ histogram(140)= 0 7640 1.843e+05 8060 + │ │ │ │ │ │ │ │ <--- 'Brand#11' ----------- 'Brand#55' + │ │ │ │ │ │ │ │ histogram(142)= 0 4240 1.9186e+05 3900 + │ │ │ │ │ │ │ │ <--- 1 ------------- 50 + │ │ │ │ │ │ │ │ histogram(143)= 0 5460 1.8978e+05 4760 + │ │ │ │ │ │ │ │ <--- 'JUMBO BAG' ------------ 'WRAP PKG' + │ │ │ │ │ │ │ ├── key: (137) + │ │ │ │ │ │ │ └── fd: (137)-->(140,142,143) + │ │ │ │ │ │ └── filters + │ │ │ │ │ │ ├── (p_size:142 >= 1) AND (p_size:142 <= 10) [type=bool, outer=(142), constraints=(/142: [/1 - /10]; tight)] + │ │ │ │ │ │ ├── p_brand:140 = 'Brand#23' [type=bool, outer=(140), constraints=(/140: [/'Brand#23' - /'Brand#23']; tight), fd=()-->(140)] + │ │ │ │ │ │ └── p_container:143 IN ('MED BAG', 'MED BOX', 'MED PACK', 'MED PKG') [type=bool, outer=(143), constraints=(/143: [/'MED BAG' - /'MED BAG'] [/'MED BOX' - /'MED BOX'] [/'MED PACK' - /'MED PACK'] [/'MED PKG' - /'MED PKG']; tight)] + │ │ │ │ │ └── filters (true) + │ │ │ │ └── filters + │ │ │ │ ├── (l_quantity:123 >= 10.0) AND (l_quantity:123 <= 20.0) [type=bool, outer=(123), constraints=(/123: [/10.0 - /20.0]; tight)] + │ │ │ │ ├── l_shipmode:133 IN ('AIR', 'AIR REG') [type=bool, outer=(133), constraints=(/133: [/'AIR' - /'AIR'] [/'AIR REG' - /'AIR REG']; tight)] + │ │ │ │ └── l_shipinstruct:132 = 'DELIVER IN PERSON' [type=bool, outer=(132), constraints=(/132: [/'DELIVER IN PERSON' - /'DELIVER IN PERSON']; tight), fd=()-->(132)] + │ │ │ └── aggregations + │ │ │ ├── const-agg [as=l_partkey:62, type=int, outer=(62)] + │ │ │ │ └── l_partkey:62 [type=int] + │ │ │ ├── const-agg [as=l_quantity:65, type=float, outer=(65)] + │ │ │ │ └── l_quantity:65 [type=float] + │ │ │ ├── const-agg [as=l_extendedprice:66, type=float, outer=(66)] + │ │ │ │ └── l_extendedprice:66 [type=float] + │ │ │ ├── const-agg [as=l_discount:67, type=float, outer=(67)] + │ │ │ │ └── l_discount:67 [type=float] + │ │ │ ├── const-agg [as=l_shipinstruct:74, type=char, outer=(74)] + │ │ │ │ └── l_shipinstruct:74 [type=char] + │ │ │ ├── const-agg [as=l_shipmode:75, type=char, outer=(75)] + │ │ │ │ └── l_shipmode:75 [type=char] + │ │ │ ├── const-agg [as=p_brand:82, type=char, outer=(82)] + │ │ │ │ └── p_brand:82 [type=char] + │ │ │ ├── const-agg [as=p_size:84, type=int, outer=(84)] + │ │ │ │ └── p_size:84 [type=int] + │ │ │ └── const-agg [as=p_container:85, type=char, outer=(85)] + │ │ │ └── p_container:85 [type=char] + │ │ └── aggregations + │ │ ├── const-agg [as=l_partkey:2, type=int, outer=(2)] + │ │ │ └── l_partkey:2 [type=int] + │ │ ├── const-agg [as=l_quantity:5, type=float, outer=(5)] + │ │ │ └── l_quantity:5 [type=float] + │ │ ├── const-agg [as=l_extendedprice:6, type=float, outer=(6)] + │ │ │ └── l_extendedprice:6 [type=float] + │ │ ├── const-agg [as=l_discount:7, type=float, outer=(7)] + │ │ │ └── l_discount:7 [type=float] + │ │ ├── const-agg [as=l_shipinstruct:14, type=char, outer=(14)] + │ │ │ └── l_shipinstruct:14 [type=char] + │ │ ├── const-agg [as=l_shipmode:15, type=char, outer=(15)] + │ │ │ └── l_shipmode:15 [type=char] + │ │ ├── const-agg [as=p_brand:22, type=char, outer=(22)] + │ │ │ └── p_brand:22 [type=char] + │ │ ├── const-agg [as=p_size:24, type=int, outer=(24)] + │ │ │ └── p_size:24 [type=int] + │ │ └── const-agg [as=p_container:25, type=char, outer=(25)] + │ │ └── p_container:25 [type=char] │ └── projections │ └── l_extendedprice:6 * (1.0 - l_discount:7) [as=column30:30, type=float, outer=(6,7), immutable] └── aggregations @@ -148,7 +314,7 @@ column_names row_count distinct_count null_count column_names row_count_est row_count_err distinct_count_est distinct_count_err null_count_est null_count_err {column30} 186.00 1.54 186.00 1.54 0.00 1.00 -----Stats for q19_inner_join_3---- +----Stats for q19_project_3---- column_names row_count distinct_count null_count {l_discount} 121 11 0 {l_extendedprice} 121 118 0 @@ -173,41 +339,287 @@ column_names row_count_est row_count_err distinct_count_est distinct_co {p_partkey} 186.00 1.54 186.00 1.81 0.00 1.00 {p_size} 186.00 1.54 17.00 1.21 0.00 1.00 -----Stats for q19_select_4---- +----Stats for q19_distinct_on_4---- column_names row_count distinct_count null_count -{l_discount} 214377 11 0 -{l_extendedprice} 214377 188952 0 -{l_partkey} 214377 131422 0 -{l_quantity} 214377 50 0 -{l_shipinstruct} 214377 1 0 -{l_shipmode} 214377 1 0 +{l_discount} 121 11 0 +{l_extendedprice} 121 118 0 +{l_linenumber} 121 7 0 +{l_orderkey} 121 121 0 +{l_partkey} 121 103 0 +{l_quantity} 121 29 0 +{l_shipinstruct} 121 1 0 +{l_shipmode} 121 1 0 +{p_brand} 121 3 0 +{p_container} 121 12 0 +{p_partkey} 121 103 0 +{p_size} 121 14 0 +~~~~ +column_names row_count_est row_count_err distinct_count_est distinct_count_err null_count_est null_count_err +{l_discount} 182.00 1.50 182.00 16.55 <== 0.00 1.00 +{l_extendedprice} 182.00 1.50 182.00 1.54 0.00 1.00 +{l_linenumber} 182.00 1.50 14.00 2.00 <== 0.00 1.00 +{l_orderkey} 182.00 1.50 182.00 1.50 0.00 1.00 +{l_partkey} 182.00 1.50 182.00 1.77 0.00 1.00 +{l_quantity} 182.00 1.50 182.00 6.28 <== 0.00 1.00 +{l_shipinstruct} 182.00 1.50 182.00 182.00 <== 0.00 1.00 +{l_shipmode} 182.00 1.50 182.00 182.00 <== 0.00 1.00 +{p_brand} 182.00 1.50 182.00 60.67 <== 0.00 1.00 +{p_container} 182.00 1.50 182.00 15.17 <== 0.00 1.00 +{p_partkey} 182.00 1.50 163.00 1.58 0.00 1.00 +{p_size} 182.00 1.50 182.00 13.00 <== 0.00 1.00 + +----Stats for q19_union_all_5---- +column_names row_count distinct_count null_count +{l_discount} 121 11 0 +{l_extendedprice} 121 118 0 +{l_linenumber} 121 7 0 +{l_orderkey} 121 121 0 +{l_partkey} 121 103 0 +{l_quantity} 121 29 0 +{l_shipinstruct} 121 1 0 +{l_shipmode} 121 1 0 +{p_brand} 121 3 0 +{p_container} 121 12 0 +{p_partkey} 121 103 0 +{p_size} 121 14 0 +~~~~ +column_names row_count_est row_count_err distinct_count_est distinct_count_err null_count_est null_count_err +{l_discount} 182.00 1.50 22.00 2.00 <== 0.00 1.00 +{l_extendedprice} 182.00 1.50 182.00 1.54 0.00 1.00 +{l_linenumber} 182.00 1.50 14.00 2.00 <== 0.00 1.00 +{l_orderkey} 182.00 1.50 182.00 1.50 0.00 1.00 +{l_partkey} 182.00 1.50 163.00 1.58 0.00 1.00 +{l_quantity} 182.00 1.50 16.00 1.81 0.00 1.00 +{l_shipinstruct} 182.00 1.50 2.00 2.00 <== 0.00 1.00 +{l_shipmode} 182.00 1.50 4.00 4.00 <== 0.00 1.00 +{p_brand} 182.00 1.50 3.00 1.00 0.00 1.00 +{p_container} 182.00 1.50 12.00 1.00 0.00 1.00 +{p_partkey} 182.00 1.50 163.00 1.58 0.00 1.00 +{p_size} 182.00 1.50 22.00 1.57 0.00 1.00 + +----Stats for q19_lookup_join_6---- +column_names row_count distinct_count null_count +{l_discount} 25 9 0 +{l_extendedprice} 25 23 0 +{l_linenumber} 25 7 0 +{l_orderkey} 25 25 0 +{l_partkey} 25 21 0 +{l_quantity} 25 10 0 +{l_shipinstruct} 25 1 0 +{l_shipmode} 25 1 0 +{p_brand} 25 1 0 +{p_container} 25 4 0 +{p_partkey} 25 21 0 +{p_size} 25 5 0 +~~~~ +column_names row_count_est row_count_err distinct_count_est distinct_count_err null_count_est null_count_err +{l_discount} 100.00 4.00 <== 11.00 1.22 0.00 1.00 +{l_extendedprice} 100.00 4.00 <== 100.00 4.35 <== 0.00 1.00 +{l_linenumber} 100.00 4.00 <== 7.00 1.00 0.00 1.00 +{l_orderkey} 100.00 4.00 <== 100.00 4.00 <== 0.00 1.00 +{l_partkey} 100.00 4.00 <== 81.00 3.86 <== 0.00 1.00 +{l_quantity} 100.00 4.00 <== 11.00 1.10 0.00 1.00 +{l_shipinstruct} 100.00 4.00 <== 1.00 1.00 0.00 1.00 +{l_shipmode} 100.00 4.00 <== 2.00 2.00 <== 0.00 1.00 +{p_brand} 100.00 4.00 <== 1.00 1.00 0.00 1.00 +{p_container} 100.00 4.00 <== 4.00 1.00 0.00 1.00 +{p_partkey} 100.00 4.00 <== 81.00 3.86 <== 0.00 1.00 +{p_size} 100.00 4.00 <== 5.00 1.00 0.00 1.00 + +----Stats for q19_lookup_join_7---- +column_names row_count distinct_count null_count +{l_linenumber} 2622 7 0 +{l_orderkey} 2622 2617 0 +{l_partkey} 2622 88 0 +{p_brand} 2622 1 0 +{p_container} 2622 4 0 +{p_partkey} 2622 88 0 +{p_size} 2622 5 0 +~~~~ +column_names row_count_est row_count_err distinct_count_est distinct_count_err null_count_est null_count_err +{l_linenumber} 2438.00 1.08 7.00 1.00 0.00 1.00 +{l_orderkey} 2438.00 1.08 2436.00 1.07 0.00 1.00 +{l_partkey} 2438.00 1.08 81.00 1.09 0.00 1.00 +{p_brand} 2438.00 1.08 1.00 1.00 0.00 1.00 +{p_container} 2438.00 1.08 4.00 1.00 0.00 1.00 +{p_partkey} 2438.00 1.08 81.00 1.09 0.00 1.00 +{p_size} 2438.00 1.08 5.00 1.00 0.00 1.00 + +----Stats for q19_select_8---- +column_names row_count distinct_count null_count +{p_brand} 88 1 0 +{p_container} 88 4 0 +{p_partkey} 88 88 0 +{p_size} 88 5 0 +~~~~ +column_names row_count_est row_count_err distinct_count_est distinct_count_err null_count_est null_count_err +{p_brand} 81.00 1.09 1.00 1.00 0.00 1.00 +{p_container} 81.00 1.09 4.00 1.00 0.00 1.00 +{p_partkey} 81.00 1.09 81.00 1.09 0.00 1.00 +{p_size} 81.00 1.09 5.00 1.00 0.00 1.00 + +----Stats for q19_scan_9---- +column_names row_count distinct_count null_count +{p_brand} 200000 25 0 +{p_container} 200000 40 0 +{p_partkey} 200000 199241 0 +{p_size} 200000 50 0 +~~~~ +column_names row_count_est row_count_err distinct_count_est distinct_count_err null_count_est null_count_err +{p_brand} 200000.00 1.00 25.00 1.00 0.00 1.00 +{p_container} 200000.00 1.00 40.00 1.00 0.00 1.00 +{p_partkey} 200000.00 1.00 199241.00 1.00 0.00 1.00 +{p_size} 200000.00 1.00 50.00 1.00 0.00 1.00 + +----Stats for q19_project_10---- +column_names row_count distinct_count null_count +{l_discount} 96 11 0 +{l_extendedprice} 96 95 0 +{l_linenumber} 96 7 0 +{l_orderkey} 96 96 0 +{l_partkey} 96 82 0 +{l_quantity} 96 21 0 +{l_shipinstruct} 96 1 0 +{l_shipmode} 96 1 0 +{p_brand} 96 2 0 +{p_container} 96 8 0 +{p_partkey} 96 82 0 +{p_size} 96 14 0 +~~~~ +column_names row_count_est row_count_err distinct_count_est distinct_count_err null_count_est null_count_err +{l_discount} 82.00 1.17 11.00 1.00 0.00 1.00 +{l_extendedprice} 82.00 1.17 82.00 1.16 0.00 1.00 +{l_linenumber} 82.00 1.17 7.00 1.00 0.00 1.00 +{l_orderkey} 82.00 1.17 82.00 1.17 0.00 1.00 +{l_partkey} 82.00 1.17 82.00 1.00 0.00 1.00 +{l_quantity} 82.00 1.17 6.00 3.50 <== 0.00 1.00 +{l_shipinstruct} 82.00 1.17 1.00 1.00 0.00 1.00 +{l_shipmode} 82.00 1.17 2.00 2.00 <== 0.00 1.00 +{p_brand} 82.00 1.17 2.00 1.00 0.00 1.00 +{p_container} 82.00 1.17 8.00 1.00 0.00 1.00 +{p_partkey} 82.00 1.17 82.00 1.00 0.00 1.00 +{p_size} 82.00 1.17 17.00 1.21 0.00 1.00 + +----Stats for q19_distinct_on_11---- +column_names row_count distinct_count null_count +{l_discount} 96 11 0 +{l_extendedprice} 96 95 0 +{l_linenumber} 96 7 0 +{l_orderkey} 96 96 0 +{l_partkey} 96 82 0 +{l_quantity} 96 21 0 +{l_shipinstruct} 96 1 0 +{l_shipmode} 96 1 0 +{p_brand} 96 2 0 +{p_container} 96 8 0 +{p_partkey} 96 82 0 +{p_size} 96 14 0 +~~~~ +column_names row_count_est row_count_err distinct_count_est distinct_count_err null_count_est null_count_err +{l_discount} 487.00 5.07 <== 487.00 44.27 <== 0.00 1.00 +{l_extendedprice} 487.00 5.07 <== 487.00 5.13 <== 0.00 1.00 +{l_linenumber} 487.00 5.07 <== 14.00 2.00 <== 0.00 1.00 +{l_orderkey} 487.00 5.07 <== 486.00 5.06 <== 0.00 1.00 +{l_partkey} 487.00 5.07 <== 487.00 5.94 <== 0.00 1.00 +{l_quantity} 487.00 5.07 <== 487.00 23.19 <== 0.00 1.00 +{l_shipinstruct} 487.00 5.07 <== 487.00 487.00 <== 0.00 1.00 +{l_shipmode} 487.00 5.07 <== 487.00 487.00 <== 0.00 1.00 +{p_brand} 487.00 5.07 <== 487.00 243.50 <== 0.00 1.00 +{p_container} 487.00 5.07 <== 487.00 60.88 <== 0.00 1.00 +{p_partkey} 487.00 5.07 <== 402.00 4.90 <== 0.00 1.00 +{p_size} 487.00 5.07 <== 487.00 34.79 <== 0.00 1.00 + +----Stats for q19_union_all_12---- +column_names row_count distinct_count null_count +{l_discount} 96 11 0 +{l_extendedprice} 96 95 0 +{l_linenumber} 96 7 0 +{l_orderkey} 96 96 0 +{l_partkey} 96 82 0 +{l_quantity} 96 21 0 +{l_shipinstruct} 96 1 0 +{l_shipmode} 96 1 0 +{p_brand} 96 2 0 +{p_container} 96 8 0 +{p_partkey} 96 82 0 +{p_size} 96 14 0 ~~~~ column_names row_count_est row_count_err distinct_count_est distinct_count_err null_count_est null_count_err -{l_discount} 416015.00 1.94 <== 11.00 1.00 0.00 1.00 -{l_extendedprice} 416015.00 1.94 <== 344687.00 1.82 0.00 1.00 -{l_partkey} 416015.00 1.94 <== 176353.00 1.34 0.00 1.00 -{l_quantity} 416015.00 1.94 <== 50.00 1.00 0.00 1.00 -{l_shipinstruct} 416015.00 1.94 <== 1.00 1.00 0.00 1.00 -{l_shipmode} 416015.00 1.94 <== 2.00 2.00 <== 0.00 1.00 - -----Stats for q19_scan_5---- +{l_discount} 487.00 5.07 <== 22.00 2.00 <== 0.00 1.00 +{l_extendedprice} 487.00 5.07 <== 486.00 5.12 <== 0.00 1.00 +{l_linenumber} 487.00 5.07 <== 14.00 2.00 <== 0.00 1.00 +{l_orderkey} 487.00 5.07 <== 486.00 5.06 <== 0.00 1.00 +{l_partkey} 487.00 5.07 <== 402.00 4.90 <== 0.00 1.00 +{l_quantity} 487.00 5.07 <== 20.00 1.05 0.00 1.00 +{l_shipinstruct} 487.00 5.07 <== 2.00 2.00 <== 0.00 1.00 +{l_shipmode} 487.00 5.07 <== 4.00 4.00 <== 0.00 1.00 +{p_brand} 487.00 5.07 <== 2.00 1.00 0.00 1.00 +{p_container} 487.00 5.07 <== 8.00 1.00 0.00 1.00 +{p_partkey} 487.00 5.07 <== 402.00 4.90 <== 0.00 1.00 +{p_size} 487.00 5.07 <== 25.00 1.79 0.00 1.00 + +----Stats for q19_lookup_join_13---- column_names row_count distinct_count null_count -{l_discount} 6001215 11 0 -{l_extendedprice} 6001215 925955 0 -{l_partkey} 6001215 199241 0 -{l_quantity} 6001215 50 0 -{l_shipinstruct} 6001215 4 0 -{l_shipmode} 6001215 7 0 +{l_discount} 56 11 0 +{l_extendedprice} 56 56 0 +{l_linenumber} 56 7 0 +{l_orderkey} 56 56 0 +{l_partkey} 56 48 0 +{l_quantity} 56 11 0 +{l_shipinstruct} 56 1 0 +{l_shipmode} 56 1 0 +{p_brand} 56 1 0 +{p_container} 56 4 0 +{p_partkey} 56 48 0 +{p_size} 56 12 0 ~~~~ column_names row_count_est row_count_err distinct_count_est distinct_count_err null_count_est null_count_err -{l_discount} 6001215.00 1.00 11.00 1.00 0.00 1.00 -{l_extendedprice} 6001215.00 1.00 925955.00 1.00 0.00 1.00 -{l_partkey} 6001215.00 1.00 199241.00 1.00 0.00 1.00 -{l_quantity} 6001215.00 1.00 50.00 1.00 0.00 1.00 -{l_shipinstruct} 6001215.00 1.00 4.00 1.00 0.00 1.00 -{l_shipmode} 6001215.00 1.00 7.00 1.00 0.00 1.00 - -----Stats for q19_select_6---- +{l_discount} 292.00 5.21 <== 11.00 1.00 0.00 1.00 +{l_extendedprice} 292.00 5.21 <== 291.00 5.20 <== 0.00 1.00 +{l_linenumber} 292.00 5.21 <== 7.00 1.00 0.00 1.00 +{l_orderkey} 292.00 5.21 <== 291.00 5.20 <== 0.00 1.00 +{l_partkey} 292.00 5.21 <== 241.00 5.02 <== 0.00 1.00 +{l_quantity} 292.00 5.21 <== 10.00 1.10 0.00 1.00 +{l_shipinstruct} 292.00 5.21 <== 1.00 1.00 0.00 1.00 +{l_shipmode} 292.00 5.21 <== 2.00 2.00 <== 0.00 1.00 +{p_brand} 292.00 5.21 <== 1.00 1.00 0.00 1.00 +{p_container} 292.00 5.21 <== 4.00 1.00 0.00 1.00 +{p_partkey} 292.00 5.21 <== 241.00 5.02 <== 0.00 1.00 +{p_size} 292.00 5.21 <== 15.00 1.25 0.00 1.00 + +----Stats for q19_lookup_join_14---- +column_names row_count distinct_count null_count +{l_linenumber} 7020 7 0 +{l_orderkey} 7020 7016 0 +{l_partkey} 7020 238 0 +{p_brand} 7020 1 0 +{p_container} 7020 4 0 +{p_partkey} 7020 238 0 +{p_size} 7020 15 0 +~~~~ +column_names row_count_est row_count_err distinct_count_est distinct_count_err null_count_est null_count_err +{l_linenumber} 7256.00 1.03 7.00 1.00 0.00 1.00 +{l_orderkey} 7256.00 1.03 7239.00 1.03 0.00 1.00 +{l_partkey} 7256.00 1.03 241.00 1.01 0.00 1.00 +{p_brand} 7256.00 1.03 1.00 1.00 0.00 1.00 +{p_container} 7256.00 1.03 4.00 1.00 0.00 1.00 +{p_partkey} 7256.00 1.03 241.00 1.01 0.00 1.00 +{p_size} 7256.00 1.03 15.00 1.00 0.00 1.00 + +----Stats for q19_select_15---- +column_names row_count distinct_count null_count +{p_brand} 238 1 0 +{p_container} 238 4 0 +{p_partkey} 238 238 0 +{p_size} 238 15 0 +~~~~ +column_names row_count_est row_count_err distinct_count_est distinct_count_err null_count_est null_count_err +{p_brand} 241.00 1.01 1.00 1.00 0.00 1.00 +{p_container} 241.00 1.01 4.00 1.00 0.00 1.00 +{p_partkey} 241.00 1.01 241.00 1.01 0.00 1.00 +{p_size} 241.00 1.01 15.00 1.00 0.00 1.00 + +----Stats for q19_scan_16---- column_names row_count distinct_count null_count {p_brand} 200000 25 0 {p_container} 200000 40 0 @@ -220,7 +632,68 @@ column_names row_count_est row_count_err distinct_count_est distinct_count_ {p_partkey} 200000.00 1.00 199241.00 1.00 0.00 1.00 {p_size} 200000.00 1.00 50.00 1.00 0.00 1.00 -----Stats for q19_scan_7---- +----Stats for q19_lookup_join_17---- +column_names row_count distinct_count null_count +{l_discount} 40 11 0 +{l_extendedprice} 40 39 0 +{l_linenumber} 40 7 0 +{l_orderkey} 40 40 0 +{l_partkey} 40 34 0 +{l_quantity} 40 11 0 +{l_shipinstruct} 40 1 0 +{l_shipmode} 40 1 0 +{p_brand} 40 1 0 +{p_container} 40 4 0 +{p_partkey} 40 34 0 +{p_size} 40 10 0 +~~~~ +column_names row_count_est row_count_err distinct_count_est distinct_count_err null_count_est null_count_err +{l_discount} 195.00 4.88 <== 11.00 1.00 0.00 1.00 +{l_extendedprice} 195.00 4.88 <== 195.00 5.00 <== 0.00 1.00 +{l_linenumber} 195.00 4.88 <== 7.00 1.00 0.00 1.00 +{l_orderkey} 195.00 4.88 <== 195.00 4.88 <== 0.00 1.00 +{l_partkey} 195.00 4.88 <== 161.00 4.74 <== 0.00 1.00 +{l_quantity} 195.00 4.88 <== 10.00 1.10 0.00 1.00 +{l_shipinstruct} 195.00 4.88 <== 1.00 1.00 0.00 1.00 +{l_shipmode} 195.00 4.88 <== 2.00 2.00 <== 0.00 1.00 +{p_brand} 195.00 4.88 <== 1.00 1.00 0.00 1.00 +{p_container} 195.00 4.88 <== 4.00 1.00 0.00 1.00 +{p_partkey} 195.00 4.88 <== 161.00 4.74 <== 0.00 1.00 +{p_size} 195.00 4.88 <== 10.00 1.00 0.00 1.00 + +----Stats for q19_lookup_join_18---- +column_names row_count distinct_count null_count +{l_linenumber} 4659 7 0 +{l_orderkey} 4659 4593 0 +{l_partkey} 4659 159 0 +{p_brand} 4659 1 0 +{p_container} 4659 4 0 +{p_partkey} 4659 159 0 +{p_size} 4659 10 0 +~~~~ +column_names row_count_est row_count_err distinct_count_est distinct_count_err null_count_est null_count_err +{l_linenumber} 4847.00 1.04 7.00 1.00 0.00 1.00 +{l_orderkey} 4847.00 1.04 4840.00 1.05 0.00 1.00 +{l_partkey} 4847.00 1.04 161.00 1.01 0.00 1.00 +{p_brand} 4847.00 1.04 1.00 1.00 0.00 1.00 +{p_container} 4847.00 1.04 4.00 1.00 0.00 1.00 +{p_partkey} 4847.00 1.04 161.00 1.01 0.00 1.00 +{p_size} 4847.00 1.04 10.00 1.00 0.00 1.00 + +----Stats for q19_select_19---- +column_names row_count distinct_count null_count +{p_brand} 159 1 0 +{p_container} 159 4 0 +{p_partkey} 159 159 0 +{p_size} 159 10 0 +~~~~ +column_names row_count_est row_count_err distinct_count_est distinct_count_err null_count_est null_count_err +{p_brand} 161.00 1.01 1.00 1.00 0.00 1.00 +{p_container} 161.00 1.01 4.00 1.00 0.00 1.00 +{p_partkey} 161.00 1.01 161.00 1.01 0.00 1.00 +{p_size} 161.00 1.01 10.00 1.00 0.00 1.00 + +----Stats for q19_scan_20---- column_names row_count distinct_count null_count {p_brand} 200000 25 0 {p_container} 200000 40 0 diff --git a/pkg/sql/opt/testutils/opttester/opt_tester.go b/pkg/sql/opt/testutils/opttester/opt_tester.go index 5bc2c386bc7c..8e9cf27639de 100644 --- a/pkg/sql/opt/testutils/opttester/opt_tester.go +++ b/pkg/sql/opt/testutils/opttester/opt_tester.go @@ -294,6 +294,7 @@ func New(catalog cat.Catalog, sql string) *OptTester { ot.evalCtx.SessionData().VariableInequalityLookupJoinEnabled = true ot.evalCtx.SessionData().OptimizerUseImprovedDisjunctionStats = true ot.evalCtx.SessionData().OptimizerUseLimitOrderingForStreamingGroupBy = true + ot.evalCtx.SessionData().OptimizerUseImprovedSplitDisjunctionForJoins = true return ot } diff --git a/pkg/sql/opt/xform/join_funcs.go b/pkg/sql/opt/xform/join_funcs.go index d4e09206d753..ef0d9a7b720b 100644 --- a/pkg/sql/opt/xform/join_funcs.go +++ b/pkg/sql/opt/xform/join_funcs.go @@ -1480,16 +1480,13 @@ func (c *CustomFuncs) splitValues( } // splitDisjunctionForJoin finds the first disjunction in the ON clause that can -// be split into an interesting pair of predicates. It returns the pair of -// predicates and the Filters item they were a part of. If an "interesting" -// disjunction is not found, ok=false is returned. +// be split into a pair of predicates. It returns the pair of predicates and the +// Filters item they were a part of. If a disjunction is not found, ok=false is +// returned. // // It is expected that the left and right inputs to joinRel have been // pre-checked to be canonical scans, or Selects from canonical scans, and // origLeftScan and origRightScan refer to those scans. -// -// For details on what makes an "interesting" disjunction, see -// findInterestingDisjunctionPairForJoin. func (c *CustomFuncs) splitDisjunctionForJoin( joinRel memo.RelExpr, filters memo.FiltersExpr, @@ -1504,7 +1501,7 @@ func (c *CustomFuncs) splitDisjunctionForJoin( for i := range filters { if filters[i].Condition.Op() == opt.OrOp { if leftPreds, rightPreds, ok = - c.findInterestingDisjunctionPairForJoin(joinRel, &filters[i], origLeftScan, origRightScan); ok { + c.findDisjunctionPairForJoin(joinRel, &filters[i], origLeftScan, origRightScan); ok { itemToReplace = &filters[i] return leftPreds, rightPreds, itemToReplace, true } @@ -1528,12 +1525,11 @@ func (c *CustomFuncs) makeFilteredSelectForJoin( return newSelect } -// SplitJoinWithEquijoinDisjuncts checks a join relation for a disjunction of -// equijoin predicates in an InnerJoin, SemiJoin or AntiJoin. If present, and -// the inputs to the join are canonical scans, or Selects from canonical scans, -// it builds two new join relations of the same join type as the original, but -// with one disjunct assigned to firstJoin and the remaining disjuncts assigned -// to secondJoin. +// SplitJoinWithDisjuncts checks a join relation for a disjunction of predicates +// in an InnerJoin, SemiJoin or AntiJoin. If present, and the inputs to the join +// are canonical scans, or Selects from canonical scans, it builds two new join +// relations of the same join type as the original, but with one disjunct +// assigned to firstJoin and the remaining disjuncts assigned to secondJoin. // // In the case of inner join, newRelationCols contains the column ids from the // original Scans in the left and right inputs plus primary key columns from @@ -1544,9 +1540,10 @@ func (c *CustomFuncs) makeFilteredSelectForJoin( // aggCols contains the non-key columns of the left and right inputs. // groupingCols contains the primary key columns of the left and right inputs, // needed for deduplicating results. -// If there is no disjunction of equijoin predicates, or the join type is not -// one of the supported join types listed above, ok=false is returned. -func (c *CustomFuncs) SplitJoinWithEquijoinDisjuncts( +// +// If there is no disjunction of predicates, or the join type is not one of the +// supported join types listed above, ok=false is returned. +func (c *CustomFuncs) SplitJoinWithDisjuncts( joinRel memo.RelExpr, joinFilters memo.FiltersExpr, ) ( firstJoin memo.RelExpr, @@ -1768,25 +1765,20 @@ func (c *CustomFuncs) CanHoistProjectInput(relation memo.RelExpr) (ok bool) { return ok } -// findInterestingDisjunctionPairForJoin groups disjunction subexpressions into -// an "interesting" pair of join predicates. +// findDisjunctionPairForJoin groups disjunction subexpressions into a pair of +// join predicates. // -// An "interesting" pair of predicates is one where one predicate is an -// equality predicate which could enable more performant joins than cross join, -// such as hash join or lookup join. At least one predicate in the disjunction -// must be an equality join term referencing both input relations. When there -// are more than two predicates, the deepest leaf node in the left depth OrExpr -// tree is returned as "left" and the remaining predicates are built into a -// brand new OrExpr chain and returned as "right". +// When there are more than two predicates, the deepest leaf node in the left +// depth OrExpr tree is returned as "left" and the remaining predicates are +// built into a brand new OrExpr chain and returned as "right". // // It is expected that the left and right inputs to joinRel have been // pre-checked to be canonical scans, or Selects from canonical scans, and // leftScan and rightScan refer to those scans. // -// findInterestingDisjunctionPairForJoin returns an ok=false if at least one of -// the ORed predicates is not an equality join term referencing both input -// relations, or if joinRel is not a join relation. -func (c *CustomFuncs) findInterestingDisjunctionPairForJoin( +// findDisjunctionPairForJoin returns ok=false if joinRel is not a join +// relation. +func (c *CustomFuncs) findDisjunctionPairForJoin( joinRel memo.RelExpr, filter *memo.FiltersItem, leftScan *memo.ScanExpr, rightScan *memo.ScanExpr, ) (left opt.ScalarExpr, right opt.ScalarExpr, ok bool) { if !opt.IsJoinOp(joinRel) { @@ -1805,9 +1797,8 @@ func (c *CustomFuncs) findInterestingDisjunctionPairForJoin( leftColSet := c.OutputCols(leftScan) rightColSet := c.OutputCols(rightScan) - // An ANDed expression is interesting if it has at least one equality join - // predicate. - interesting := false + // hasJoinEquality returns true if an ANDed expression has at least one + // equality join predicate. var hasJoinEquality func(opt.ScalarExpr) bool hasJoinEquality = func(expr opt.ScalarExpr) bool { switch t := expr.(type) { @@ -1824,14 +1815,18 @@ func (c *CustomFuncs) findInterestingDisjunctionPairForJoin( // Traverse all adjacent OrExpr. var collect func(opt.ScalarExpr) collect = func(expr opt.ScalarExpr) { - interesting = false + interesting := false switch t := expr.(type) { case *memo.OrExpr: collect(t.Left) collect(t.Right) return default: - interesting = hasJoinEquality(expr) + if c.e.evalCtx.SessionData().OptimizerUseImprovedSplitDisjunctionForJoins { + interesting = true + } else { + interesting = hasJoinEquality(expr) + } } if interesting && len(leftExprs) == 0 { diff --git a/pkg/sql/opt/xform/rules/join.opt b/pkg/sql/opt/xform/rules/join.opt index baa7c58e2094..aa331ddeaa59 100644 --- a/pkg/sql/opt/xform/rules/join.opt +++ b/pkg/sql/opt/xform/rules/join.opt @@ -127,18 +127,16 @@ # SplitDisjunctionOfJoinTerms splits disjunctions (OR expressions) of ON clause # predicates of an inner or semi join into a Union of two Join expressions, the # first containing the left subexpression of the OR expression and the second -# containing the right subexpression. -# All other filter items in the original expression are preserved in the new -# Join expressions. The logical Union is evaluated as a UNION ALL followed by a -# distinct sort on the primary key columns of both the left and right input in -# the case of inner join, or in the case or semijoin, the primary key columns -# of the left. -# -# The call to SplitJoinWithEquijoinDisjuncts adds primary key columns to the -# original Scan ColSet which the replace pattern removes by adding a Project as -# the last operation. -# Inclusion of the primary keys is required to prevent the generated Union from -# duplicating rows that have the same selected values. +# containing the right subexpression. All other filter items in the original +# expression are preserved in the new Join expressions. The logical Union is +# evaluated as a UNION ALL followed by a distinct sort on the primary key +# columns of both the left and right input in the case of inner join, or in the +# case or semijoin, the primary key columns of the left. +# +# The call to SplitJoinWithDisjuncts adds primary key columns to the original +# Scan ColSet which the replace pattern removes by adding a Project as the last +# operation. Inclusion of the primary keys is required to prevent the generated +# Union from duplicating rows that have the same selected values. # # This can produce better query plans in cases where indexes cover both sides of # the OR expression, or to enable hash-based join methods instead of cross join. @@ -160,7 +158,7 @@ $aggCols $groupingCols $ok - ):(SplitJoinWithEquijoinDisjuncts (Root) $on) + ):(SplitJoinWithDisjuncts (Root) $on) $ok ) * @@ -188,8 +186,8 @@ # clause predicates of an antijoin into a Union of two AntiJoin expressions, the # first containing the left subexpression of the OR expression and the second # containing the right subexpression. This rule is identical to -# SplitDisjunctionOfJoinTerms, except the INTERSECT ALL set operation is used -# in place of UNION ALL. +# SplitDisjunctionOfJoinTerms, except the INTERSECT ALL set operation is used in +# place of UNION ALL. [SplitDisjunctionOfAntiJoinTerms, Explore] (AntiJoin * @@ -203,7 +201,7 @@ $aggCols $groupingCols $ok - ):(SplitJoinWithEquijoinDisjuncts (Root) $on) + ):(SplitJoinWithDisjuncts (Root) $on) $ok ) * diff --git a/pkg/sql/opt/xform/testdata/external/tpch b/pkg/sql/opt/xform/testdata/external/tpch index 08ae89801b81..8d43f1f7600e 100644 --- a/pkg/sql/opt/xform/testdata/external/tpch +++ b/pkg/sql/opt/xform/testdata/external/tpch @@ -2049,31 +2049,155 @@ scalar-group-by ├── project │ ├── columns: column30:30!null │ ├── immutable - │ ├── inner-join (hash) + │ ├── project │ │ ├── columns: l_partkey:2!null l_quantity:5!null l_extendedprice:6!null l_discount:7!null l_shipinstruct:14!null l_shipmode:15!null p_partkey:19!null p_brand:22!null p_size:24!null p_container:25!null - │ │ ├── multiplicity: left-rows(zero-or-one), right-rows(zero-or-more) │ │ ├── fd: ()-->(14), (19)-->(22,24,25), (2)==(19), (19)==(2) - │ │ ├── select - │ │ │ ├── columns: l_partkey:2!null l_quantity:5!null l_extendedprice:6!null l_discount:7!null l_shipinstruct:14!null l_shipmode:15!null - │ │ │ ├── fd: ()-->(14) - │ │ │ ├── scan lineitem - │ │ │ │ └── columns: l_partkey:2!null l_quantity:5!null l_extendedprice:6!null l_discount:7!null l_shipinstruct:14!null l_shipmode:15!null - │ │ │ └── filters - │ │ │ ├── l_shipmode:15 IN ('AIR', 'AIR REG') [outer=(15), constraints=(/15: [/'AIR' - /'AIR'] [/'AIR REG' - /'AIR REG']; tight)] - │ │ │ └── l_shipinstruct:14 = 'DELIVER IN PERSON' [outer=(14), constraints=(/14: [/'DELIVER IN PERSON' - /'DELIVER IN PERSON']; tight), fd=()-->(14)] - │ │ ├── select - │ │ │ ├── columns: p_partkey:19!null p_brand:22!null p_size:24!null p_container:25!null - │ │ │ ├── key: (19) - │ │ │ ├── fd: (19)-->(22,24,25) - │ │ │ ├── scan part - │ │ │ │ ├── columns: p_partkey:19!null p_brand:22!null p_size:24!null p_container:25!null - │ │ │ │ ├── key: (19) - │ │ │ │ └── fd: (19)-->(22,24,25) - │ │ │ └── filters - │ │ │ └── p_size:24 >= 1 [outer=(24), constraints=(/24: [/1 - ]; tight)] - │ │ └── filters - │ │ ├── p_partkey:19 = l_partkey:2 [outer=(2,19), constraints=(/2: (/NULL - ]; /19: (/NULL - ]), fd=(2)==(19), (19)==(2)] - │ │ └── ((((((p_brand:22 = 'Brand#12') AND (p_container:25 IN ('SM BOX', 'SM CASE', 'SM PACK', 'SM PKG'))) AND (l_quantity:5 >= 1.0)) AND (l_quantity:5 <= 11.0)) AND (p_size:24 <= 5)) OR (((((p_brand:22 = 'Brand#23') AND (p_container:25 IN ('MED BAG', 'MED BOX', 'MED PACK', 'MED PKG'))) AND (l_quantity:5 >= 10.0)) AND (l_quantity:5 <= 20.0)) AND (p_size:24 <= 10))) OR (((((p_brand:22 = 'Brand#34') AND (p_container:25 IN ('LG BOX', 'LG CASE', 'LG PACK', 'LG PKG'))) AND (l_quantity:5 >= 20.0)) AND (l_quantity:5 <= 30.0)) AND (p_size:24 <= 15)) [outer=(5,22,24,25), constraints=(/5: [/1.0 - /30.0]; /22: [/'Brand#12' - /'Brand#12'] [/'Brand#23' - /'Brand#23'] [/'Brand#34' - /'Brand#34']; /24: (/NULL - /15]; /25: [/'LG BOX' - /'LG BOX'] [/'LG CASE' - /'LG CASE'] [/'LG PACK' - /'LG PACK'] [/'LG PKG' - /'LG PKG'] [/'MED BAG' - /'MED BAG'] [/'MED BOX' - /'MED BOX'] [/'MED PACK' - /'MED PACK'] [/'MED PKG' - /'MED PKG'] [/'SM BOX' - /'SM BOX'] [/'SM CASE' - /'SM CASE'] [/'SM PACK' - /'SM PACK'] [/'SM PKG' - /'SM PKG'])] + │ │ └── distinct-on + │ │ ├── columns: l_orderkey:1!null l_partkey:2!null l_linenumber:4!null l_quantity:5!null l_extendedprice:6!null l_discount:7!null l_shipinstruct:14!null l_shipmode:15!null p_partkey:19!null p_brand:22!null p_size:24!null p_container:25!null + │ │ ├── grouping columns: l_orderkey:1!null l_linenumber:4!null p_partkey:19!null + │ │ ├── key: (1,4,19) + │ │ ├── fd: (2)==(19), (19)==(2), (1,4,19)-->(2,5-7,14,15,22,24,25) + │ │ ├── union-all + │ │ │ ├── columns: l_orderkey:1!null l_partkey:2!null l_linenumber:4!null l_quantity:5!null l_extendedprice:6!null l_discount:7!null l_shipinstruct:14!null l_shipmode:15!null p_partkey:19!null p_brand:22!null p_size:24!null p_container:25!null + │ │ │ ├── left columns: l_orderkey:32 l_partkey:33 l_linenumber:35 l_quantity:36 l_extendedprice:37 l_discount:38 l_shipinstruct:45 l_shipmode:46 p_partkey:50 p_brand:53 p_size:55 p_container:56 + │ │ │ ├── right columns: l_orderkey:61 l_partkey:62 l_linenumber:64 l_quantity:65 l_extendedprice:66 l_discount:67 l_shipinstruct:74 l_shipmode:75 p_partkey:79 p_brand:82 p_size:84 p_container:85 + │ │ │ ├── fd: (2)==(19), (19)==(2) + │ │ │ ├── inner-join (lookup lineitem) + │ │ │ │ ├── columns: l_orderkey:32!null l_partkey:33!null l_linenumber:35!null l_quantity:36!null l_extendedprice:37!null l_discount:38!null l_shipinstruct:45!null l_shipmode:46!null p_partkey:50!null p_brand:53!null p_size:55!null p_container:56!null + │ │ │ │ ├── key columns: [32 35] = [32 35] + │ │ │ │ ├── lookup columns are key + │ │ │ │ ├── key: (32,35) + │ │ │ │ ├── fd: ()-->(45,53), (32,35)-->(33,36-38,46), (50)-->(55,56), (33)==(50), (50)==(33) + │ │ │ │ ├── inner-join (lookup lineitem@l_pk) + │ │ │ │ │ ├── columns: l_orderkey:32!null l_partkey:33!null l_linenumber:35!null p_partkey:50!null p_brand:53!null p_size:55!null p_container:56!null + │ │ │ │ │ ├── key columns: [50] = [33] + │ │ │ │ │ ├── key: (32,35) + │ │ │ │ │ ├── fd: ()-->(53), (50)-->(55,56), (32,35)-->(33), (33)==(50), (50)==(33) + │ │ │ │ │ ├── select + │ │ │ │ │ │ ├── columns: p_partkey:50!null p_brand:53!null p_size:55!null p_container:56!null + │ │ │ │ │ │ ├── key: (50) + │ │ │ │ │ │ ├── fd: ()-->(53), (50)-->(55,56) + │ │ │ │ │ │ ├── scan part + │ │ │ │ │ │ │ ├── columns: p_partkey:50!null p_brand:53!null p_size:55!null p_container:56!null + │ │ │ │ │ │ │ ├── key: (50) + │ │ │ │ │ │ │ └── fd: (50)-->(53,55,56) + │ │ │ │ │ │ └── filters + │ │ │ │ │ │ ├── (p_size:55 >= 1) AND (p_size:55 <= 5) [outer=(55), constraints=(/55: [/1 - /5]; tight)] + │ │ │ │ │ │ ├── p_brand:53 = 'Brand#12' [outer=(53), constraints=(/53: [/'Brand#12' - /'Brand#12']; tight), fd=()-->(53)] + │ │ │ │ │ │ └── p_container:56 IN ('SM BOX', 'SM CASE', 'SM PACK', 'SM PKG') [outer=(56), constraints=(/56: [/'SM BOX' - /'SM BOX'] [/'SM CASE' - /'SM CASE'] [/'SM PACK' - /'SM PACK'] [/'SM PKG' - /'SM PKG']; tight)] + │ │ │ │ │ └── filters (true) + │ │ │ │ └── filters + │ │ │ │ ├── (l_quantity:36 >= 1.0) AND (l_quantity:36 <= 11.0) [outer=(36), constraints=(/36: [/1.0 - /11.0]; tight)] + │ │ │ │ ├── l_shipmode:46 IN ('AIR', 'AIR REG') [outer=(46), constraints=(/46: [/'AIR' - /'AIR'] [/'AIR REG' - /'AIR REG']; tight)] + │ │ │ │ └── l_shipinstruct:45 = 'DELIVER IN PERSON' [outer=(45), constraints=(/45: [/'DELIVER IN PERSON' - /'DELIVER IN PERSON']; tight), fd=()-->(45)] + │ │ │ └── project + │ │ │ ├── columns: l_orderkey:61!null l_partkey:62!null l_linenumber:64!null l_quantity:65!null l_extendedprice:66!null l_discount:67!null l_shipinstruct:74!null l_shipmode:75!null p_partkey:79!null p_brand:82!null p_size:84!null p_container:85!null + │ │ │ ├── key: (61,64) + │ │ │ ├── fd: ()-->(74), (61,64)-->(62,65-67,75), (79)-->(82,84,85), (62)==(79), (79)==(62) + │ │ │ └── distinct-on + │ │ │ ├── columns: l_orderkey:61!null l_partkey:62!null l_linenumber:64!null l_quantity:65!null l_extendedprice:66!null l_discount:67!null l_shipinstruct:74!null l_shipmode:75!null p_partkey:79!null p_brand:82!null p_size:84!null p_container:85!null + │ │ │ ├── grouping columns: l_orderkey:61!null l_linenumber:64!null p_partkey:79!null + │ │ │ ├── key: (61,64,79) + │ │ │ ├── fd: (62)==(79), (79)==(62), (61,64,79)-->(62,65-67,74,75,82,84,85) + │ │ │ ├── union-all + │ │ │ │ ├── columns: l_orderkey:61!null l_partkey:62!null l_linenumber:64!null l_quantity:65!null l_extendedprice:66!null l_discount:67!null l_shipinstruct:74!null l_shipmode:75!null p_partkey:79!null p_brand:82!null p_size:84!null p_container:85!null + │ │ │ │ ├── left columns: l_orderkey:90 l_partkey:91 l_linenumber:93 l_quantity:94 l_extendedprice:95 l_discount:96 l_shipinstruct:103 l_shipmode:104 p_partkey:108 p_brand:111 p_size:113 p_container:114 + │ │ │ │ ├── right columns: l_orderkey:119 l_partkey:120 l_linenumber:122 l_quantity:123 l_extendedprice:124 l_discount:125 l_shipinstruct:132 l_shipmode:133 p_partkey:137 p_brand:140 p_size:142 p_container:143 + │ │ │ │ ├── fd: (62)==(79), (79)==(62) + │ │ │ │ ├── inner-join (lookup lineitem) + │ │ │ │ │ ├── columns: l_orderkey:90!null l_partkey:91!null l_linenumber:93!null l_quantity:94!null l_extendedprice:95!null l_discount:96!null l_shipinstruct:103!null l_shipmode:104!null p_partkey:108!null p_brand:111!null p_size:113!null p_container:114!null + │ │ │ │ │ ├── key columns: [90 93] = [90 93] + │ │ │ │ │ ├── lookup columns are key + │ │ │ │ │ ├── key: (90,93) + │ │ │ │ │ ├── fd: ()-->(103,111), (90,93)-->(91,94-96,104), (108)-->(113,114), (91)==(108), (108)==(91) + │ │ │ │ │ ├── inner-join (lookup lineitem@l_pk) + │ │ │ │ │ │ ├── columns: l_orderkey:90!null l_partkey:91!null l_linenumber:93!null p_partkey:108!null p_brand:111!null p_size:113!null p_container:114!null + │ │ │ │ │ │ ├── key columns: [108] = [91] + │ │ │ │ │ │ ├── key: (90,93) + │ │ │ │ │ │ ├── fd: ()-->(111), (108)-->(113,114), (90,93)-->(91), (91)==(108), (108)==(91) + │ │ │ │ │ │ ├── select + │ │ │ │ │ │ │ ├── columns: p_partkey:108!null p_brand:111!null p_size:113!null p_container:114!null + │ │ │ │ │ │ │ ├── key: (108) + │ │ │ │ │ │ │ ├── fd: ()-->(111), (108)-->(113,114) + │ │ │ │ │ │ │ ├── scan part + │ │ │ │ │ │ │ │ ├── columns: p_partkey:108!null p_brand:111!null p_size:113!null p_container:114!null + │ │ │ │ │ │ │ │ ├── key: (108) + │ │ │ │ │ │ │ │ └── fd: (108)-->(111,113,114) + │ │ │ │ │ │ │ └── filters + │ │ │ │ │ │ │ ├── (p_size:113 >= 1) AND (p_size:113 <= 15) [outer=(113), constraints=(/113: [/1 - /15]; tight)] + │ │ │ │ │ │ │ ├── p_brand:111 = 'Brand#34' [outer=(111), constraints=(/111: [/'Brand#34' - /'Brand#34']; tight), fd=()-->(111)] + │ │ │ │ │ │ │ └── p_container:114 IN ('LG BOX', 'LG CASE', 'LG PACK', 'LG PKG') [outer=(114), constraints=(/114: [/'LG BOX' - /'LG BOX'] [/'LG CASE' - /'LG CASE'] [/'LG PACK' - /'LG PACK'] [/'LG PKG' - /'LG PKG']; tight)] + │ │ │ │ │ │ └── filters (true) + │ │ │ │ │ └── filters + │ │ │ │ │ ├── (l_quantity:94 >= 20.0) AND (l_quantity:94 <= 30.0) [outer=(94), constraints=(/94: [/20.0 - /30.0]; tight)] + │ │ │ │ │ ├── l_shipmode:104 IN ('AIR', 'AIR REG') [outer=(104), constraints=(/104: [/'AIR' - /'AIR'] [/'AIR REG' - /'AIR REG']; tight)] + │ │ │ │ │ └── l_shipinstruct:103 = 'DELIVER IN PERSON' [outer=(103), constraints=(/103: [/'DELIVER IN PERSON' - /'DELIVER IN PERSON']; tight), fd=()-->(103)] + │ │ │ │ └── inner-join (lookup lineitem) + │ │ │ │ ├── columns: l_orderkey:119!null l_partkey:120!null l_linenumber:122!null l_quantity:123!null l_extendedprice:124!null l_discount:125!null l_shipinstruct:132!null l_shipmode:133!null p_partkey:137!null p_brand:140!null p_size:142!null p_container:143!null + │ │ │ │ ├── key columns: [119 122] = [119 122] + │ │ │ │ ├── lookup columns are key + │ │ │ │ ├── key: (119,122) + │ │ │ │ ├── fd: ()-->(132,140), (119,122)-->(120,123-125,133), (137)-->(142,143), (120)==(137), (137)==(120) + │ │ │ │ ├── inner-join (lookup lineitem@l_pk) + │ │ │ │ │ ├── columns: l_orderkey:119!null l_partkey:120!null l_linenumber:122!null p_partkey:137!null p_brand:140!null p_size:142!null p_container:143!null + │ │ │ │ │ ├── key columns: [137] = [120] + │ │ │ │ │ ├── key: (119,122) + │ │ │ │ │ ├── fd: ()-->(140), (137)-->(142,143), (119,122)-->(120), (120)==(137), (137)==(120) + │ │ │ │ │ ├── select + │ │ │ │ │ │ ├── columns: p_partkey:137!null p_brand:140!null p_size:142!null p_container:143!null + │ │ │ │ │ │ ├── key: (137) + │ │ │ │ │ │ ├── fd: ()-->(140), (137)-->(142,143) + │ │ │ │ │ │ ├── scan part + │ │ │ │ │ │ │ ├── columns: p_partkey:137!null p_brand:140!null p_size:142!null p_container:143!null + │ │ │ │ │ │ │ ├── key: (137) + │ │ │ │ │ │ │ └── fd: (137)-->(140,142,143) + │ │ │ │ │ │ └── filters + │ │ │ │ │ │ ├── (p_size:142 >= 1) AND (p_size:142 <= 10) [outer=(142), constraints=(/142: [/1 - /10]; tight)] + │ │ │ │ │ │ ├── p_brand:140 = 'Brand#23' [outer=(140), constraints=(/140: [/'Brand#23' - /'Brand#23']; tight), fd=()-->(140)] + │ │ │ │ │ │ └── p_container:143 IN ('MED BAG', 'MED BOX', 'MED PACK', 'MED PKG') [outer=(143), constraints=(/143: [/'MED BAG' - /'MED BAG'] [/'MED BOX' - /'MED BOX'] [/'MED PACK' - /'MED PACK'] [/'MED PKG' - /'MED PKG']; tight)] + │ │ │ │ │ └── filters (true) + │ │ │ │ └── filters + │ │ │ │ ├── (l_quantity:123 >= 10.0) AND (l_quantity:123 <= 20.0) [outer=(123), constraints=(/123: [/10.0 - /20.0]; tight)] + │ │ │ │ ├── l_shipmode:133 IN ('AIR', 'AIR REG') [outer=(133), constraints=(/133: [/'AIR' - /'AIR'] [/'AIR REG' - /'AIR REG']; tight)] + │ │ │ │ └── l_shipinstruct:132 = 'DELIVER IN PERSON' [outer=(132), constraints=(/132: [/'DELIVER IN PERSON' - /'DELIVER IN PERSON']; tight), fd=()-->(132)] + │ │ │ └── aggregations + │ │ │ ├── const-agg [as=l_partkey:62, outer=(62)] + │ │ │ │ └── l_partkey:62 + │ │ │ ├── const-agg [as=l_quantity:65, outer=(65)] + │ │ │ │ └── l_quantity:65 + │ │ │ ├── const-agg [as=l_extendedprice:66, outer=(66)] + │ │ │ │ └── l_extendedprice:66 + │ │ │ ├── const-agg [as=l_discount:67, outer=(67)] + │ │ │ │ └── l_discount:67 + │ │ │ ├── const-agg [as=l_shipinstruct:74, outer=(74)] + │ │ │ │ └── l_shipinstruct:74 + │ │ │ ├── const-agg [as=l_shipmode:75, outer=(75)] + │ │ │ │ └── l_shipmode:75 + │ │ │ ├── const-agg [as=p_brand:82, outer=(82)] + │ │ │ │ └── p_brand:82 + │ │ │ ├── const-agg [as=p_size:84, outer=(84)] + │ │ │ │ └── p_size:84 + │ │ │ └── const-agg [as=p_container:85, outer=(85)] + │ │ │ └── p_container:85 + │ │ └── aggregations + │ │ ├── const-agg [as=l_partkey:2, outer=(2)] + │ │ │ └── l_partkey:2 + │ │ ├── const-agg [as=l_quantity:5, outer=(5)] + │ │ │ └── l_quantity:5 + │ │ ├── const-agg [as=l_extendedprice:6, outer=(6)] + │ │ │ └── l_extendedprice:6 + │ │ ├── const-agg [as=l_discount:7, outer=(7)] + │ │ │ └── l_discount:7 + │ │ ├── const-agg [as=l_shipinstruct:14, outer=(14)] + │ │ │ └── l_shipinstruct:14 + │ │ ├── const-agg [as=l_shipmode:15, outer=(15)] + │ │ │ └── l_shipmode:15 + │ │ ├── const-agg [as=p_brand:22, outer=(22)] + │ │ │ └── p_brand:22 + │ │ ├── const-agg [as=p_size:24, outer=(24)] + │ │ │ └── p_size:24 + │ │ └── const-agg [as=p_container:25, outer=(25)] + │ │ └── p_container:25 │ └── projections │ └── l_extendedprice:6 * (1.0 - l_discount:7) [as=column30:30, outer=(6,7), immutable] └── aggregations diff --git a/pkg/sql/opt/xform/testdata/physprops/ordering b/pkg/sql/opt/xform/testdata/physprops/ordering index f111f5bcbae5..f57603b9aa02 100644 --- a/pkg/sql/opt/xform/testdata/physprops/ordering +++ b/pkg/sql/opt/xform/testdata/physprops/ordering @@ -2923,28 +2923,28 @@ project ├── fd: (2)==(6), (6)==(2), (2)-->(1,5) ├── ordering: +(2|6) [actual: +2] ├── inner-join (merge) - │ ├── columns: t0_85393.c0:9 t0_85393.rowid:10!null t1_85393.c0:13 t1_85393.rowid:14!null - │ ├── left ordering: +10 - │ ├── right ordering: +14 - │ ├── key: (14) - │ ├── fd: (10)-->(9), (14)-->(13), (10)==(14), (14)==(10) - │ ├── ordering: +(10|14) [actual: +10] + │ ├── columns: t0_85393.c0:17 t0_85393.rowid:18!null t1_85393.c0:21 t1_85393.rowid:22!null + │ ├── left ordering: +18 + │ ├── right ordering: +22 + │ ├── key: (22) + │ ├── fd: (18)-->(17), (22)-->(21), (18)==(22), (22)==(18) + │ ├── ordering: +(18|22) [actual: +18] │ ├── scan t0_85393 - │ │ ├── columns: t0_85393.c0:9 t0_85393.rowid:10!null - │ │ ├── key: (10) - │ │ ├── fd: (10)-->(9) - │ │ └── ordering: +10 + │ │ ├── columns: t0_85393.c0:17 t0_85393.rowid:18!null + │ │ ├── key: (18) + │ │ ├── fd: (18)-->(17) + │ │ └── ordering: +18 │ ├── scan t1_85393 - │ │ ├── columns: t1_85393.c0:13 t1_85393.rowid:14!null - │ │ ├── key: (14) - │ │ ├── fd: (14)-->(13) - │ │ └── ordering: +14 + │ │ ├── columns: t1_85393.c0:21 t1_85393.rowid:22!null + │ │ ├── key: (22) + │ │ ├── fd: (22)-->(21) + │ │ └── ordering: +22 │ └── filters (true) └── projections - ├── t0_85393.c0:9 [as=t0_85393.c0:1, outer=(9)] - ├── t0_85393.rowid:10 [as=t0_85393.rowid:2, outer=(10)] - ├── t1_85393.c0:13 [as=t1_85393.c0:5, outer=(13)] - └── t1_85393.rowid:14 [as=t1_85393.rowid:6, outer=(14)] + ├── t0_85393.c0:17 [as=t0_85393.c0:1, outer=(17)] + ├── t0_85393.rowid:18 [as=t0_85393.rowid:2, outer=(18)] + ├── t1_85393.c0:21 [as=t1_85393.c0:5, outer=(21)] + └── t1_85393.rowid:22 [as=t1_85393.rowid:6, outer=(22)] # Regression test for #83793 - include scan columns that are constrained to be # constant in the provided ordering when they are in the output of the scan. diff --git a/pkg/sql/opt/xform/testdata/rules/disjunction_in_join b/pkg/sql/opt/xform/testdata/rules/disjunction_in_join index 19a3db8a5805..9fe4b5baadb4 100644 --- a/pkg/sql/opt/xform/testdata/rules/disjunction_in_join +++ b/pkg/sql/opt/xform/testdata/rules/disjunction_in_join @@ -25,6 +25,31 @@ CREATE TABLE d(d1 INT, d2 INT, d3 INT, d4 INT, INDEX d (d1) STORING (d2, d3, d4)) ---- +exec-ddl +CREATE TABLE e ( + e1 INT PRIMARY KEY, + e2 INT NOT NULL, + e3 INT NOT NULL, + e4 STRING NOT NULL, + e5 INT NULL, + INDEX (e2 ASC, e3 ASC, e4 ASC), + INDEX (e5 ASC), + INDEX (e3 ASC, e5 ASC, e4 ASC), + INDEX (e3 ASC) WHERE e4 IN ('a', 'b') +) +---- + +exec-ddl +CREATE TABLE f ( + f1 INT PRIMARY KEY, + f2 INT NULL, + f3 INT NULL, + f4 INT NOT NULL, + INDEX (f3 ASC), + INDEX (f2 ASC) STORING (f3) +) +---- + # -------------------------------------------------- # InnerJoin # -------------------------------------------------- @@ -366,40 +391,40 @@ project │ ├── columns: b1:1 b2:2 b3:3 b4:4 b.rowid:5!null d1:8 d2:9 d3:10 d4:11 d.rowid:12!null │ ├── left columns: b1:15 b2:16 b3:17 b4:18 b.rowid:19 d1:22 d2:23 d3:24 d4:25 d.rowid:26 │ ├── right columns: b1:29 b2:30 b3:31 b4:32 b.rowid:33 d1:36 d2:37 d3:38 d4:39 d.rowid:40 - │ ├── inner-join (hash) - │ │ ├── columns: b1:15 b2:16 b3:17!null b4:18 b.rowid:19!null d1:22 d2:23 d3:24!null d4:25 d.rowid:26!null + │ ├── inner-join (cross) + │ │ ├── columns: b1:15!null b2:16!null b3:17 b4:18 b.rowid:19!null d1:22 d2:23 d3:24 d4:25 d.rowid:26!null │ │ ├── key: (19,26) - │ │ ├── fd: (19)-->(15-18), (26)-->(22-25), (17)==(24), (24)==(17) - │ │ ├── scan b - │ │ │ ├── columns: b1:15 b2:16 b3:17 b4:18 b.rowid:19!null - │ │ │ ├── key: (19) - │ │ │ └── fd: (19)-->(15-18) + │ │ ├── fd: (19)-->(15-18), (15)==(16), (16)==(15), (26)-->(22-25) │ │ ├── scan d │ │ │ ├── columns: d1:22 d2:23 d3:24 d4:25 d.rowid:26!null │ │ │ ├── key: (26) │ │ │ └── fd: (26)-->(22-25) - │ │ └── filters - │ │ └── b3:17 = d3:24 [outer=(17,24), constraints=(/17: (/NULL - ]; /24: (/NULL - ]), fd=(17)==(24), (24)==(17)] - │ └── inner-join (cross) - │ ├── columns: b1:29!null b2:30!null b3:31 b4:32 b.rowid:33!null d1:36 d2:37 d3:38 d4:39 d.rowid:40!null + │ │ ├── select + │ │ │ ├── columns: b1:15!null b2:16!null b3:17 b4:18 b.rowid:19!null + │ │ │ ├── key: (19) + │ │ │ ├── fd: (19)-->(15-18), (15)==(16), (16)==(15) + │ │ │ ├── scan b@b_b1_b2_idx + │ │ │ │ ├── columns: b1:15!null b2:16 b3:17 b4:18 b.rowid:19!null + │ │ │ │ ├── constraint: /15/16/19: (/NULL - ] + │ │ │ │ ├── key: (19) + │ │ │ │ └── fd: (19)-->(15-18) + │ │ │ └── filters + │ │ │ └── b1:15 = b2:16 [outer=(15,16), constraints=(/15: (/NULL - ]; /16: (/NULL - ]), fd=(15)==(16), (16)==(15)] + │ │ └── filters (true) + │ └── inner-join (hash) + │ ├── columns: b1:29 b2:30 b3:31!null b4:32 b.rowid:33!null d1:36 d2:37 d3:38!null d4:39 d.rowid:40!null │ ├── key: (33,40) - │ ├── fd: (33)-->(29-32), (29)==(30), (30)==(29), (40)-->(36-39) + │ ├── fd: (33)-->(29-32), (40)-->(36-39), (31)==(38), (38)==(31) + │ ├── scan b + │ │ ├── columns: b1:29 b2:30 b3:31 b4:32 b.rowid:33!null + │ │ ├── key: (33) + │ │ └── fd: (33)-->(29-32) │ ├── scan d │ │ ├── columns: d1:36 d2:37 d3:38 d4:39 d.rowid:40!null │ │ ├── key: (40) │ │ └── fd: (40)-->(36-39) - │ ├── select - │ │ ├── columns: b1:29!null b2:30!null b3:31 b4:32 b.rowid:33!null - │ │ ├── key: (33) - │ │ ├── fd: (33)-->(29-32), (29)==(30), (30)==(29) - │ │ ├── scan b@b_b1_b2_idx - │ │ │ ├── columns: b1:29!null b2:30 b3:31 b4:32 b.rowid:33!null - │ │ │ ├── constraint: /29/30/33: (/NULL - ] - │ │ │ ├── key: (33) - │ │ │ └── fd: (33)-->(29-32) - │ │ └── filters - │ │ └── b1:29 = b2:30 [outer=(29,30), constraints=(/29: (/NULL - ]; /30: (/NULL - ]), fd=(29)==(30), (30)==(29)] - │ └── filters (true) + │ └── filters + │ └── b3:31 = d3:38 [outer=(31,38), constraints=(/31: (/NULL - ]; /38: (/NULL - ]), fd=(31)==(38), (38)==(31)] └── aggregations ├── const-agg [as=b1:1, outer=(1)] │ └── b1:1 @@ -461,103 +486,103 @@ project │ ├── columns: b1:1!null b2:2!null b3:3 b4:4 b.rowid:5!null d1:8!null d2:9 d3:10 d4:11 d.rowid:12!null │ ├── left columns: b1:29 b2:30 b3:31 b4:32 b.rowid:33 d1:36 d2:37 d3:38 d4:39 d.rowid:40 │ ├── right columns: b1:43 b2:44 b3:45 b4:46 b.rowid:47 d1:50 d2:51 d3:52 d4:53 d.rowid:54 - │ ├── inner-join (lookup d@d) + │ ├── project │ │ ├── columns: b1:29!null b2:30!null b3:31 b4:32 b.rowid:33!null d1:36!null d2:37 d3:38 d4:39 d.rowid:40!null - │ │ ├── key columns: [29] = [36] │ │ ├── key: (33,40) - │ │ ├── fd: (33)-->(29-32), (40)-->(36-39), (29)==(36), (36)==(29) - │ │ ├── distinct-on - │ │ │ ├── columns: b1:29!null b2:30!null b3:31 b4:32 b.rowid:33!null - │ │ │ ├── grouping columns: b.rowid:33!null - │ │ │ ├── key: (33) - │ │ │ ├── fd: (33)-->(29-32) - │ │ │ ├── union-all - │ │ │ │ ├── columns: b1:29!null b2:30!null b3:31 b4:32 b.rowid:33!null - │ │ │ │ ├── left columns: b1:57 b2:58 b3:59 b4:60 b.rowid:61 - │ │ │ │ ├── right columns: b1:64 b2:65 b3:66 b4:67 b.rowid:68 - │ │ │ │ ├── scan b@b_b1_b2_idx - │ │ │ │ │ ├── columns: b1:57!null b2:58!null b3:59 b4:60 b.rowid:61!null - │ │ │ │ │ ├── constraint: /57/58/61 - │ │ │ │ │ │ ├── [/0/0 - /0/0] - │ │ │ │ │ │ └── [/0/5 - /0/5] - │ │ │ │ │ ├── key: (61) - │ │ │ │ │ └── fd: ()-->(57), (61)-->(58-60) - │ │ │ │ └── select - │ │ │ │ ├── columns: b1:64!null b2:65!null b3:66 b4:67 b.rowid:68!null - │ │ │ │ ├── key: (68) - │ │ │ │ ├── fd: ()-->(65), (68)-->(64,66,67) - │ │ │ │ ├── scan b@b_b2_idx - │ │ │ │ │ ├── columns: b1:64 b2:65!null b3:66 b4:67 b.rowid:68!null - │ │ │ │ │ ├── constraint: /65/68: [/5 - /5] - │ │ │ │ │ ├── key: (68) - │ │ │ │ │ └── fd: ()-->(65), (68)-->(64,66,67) - │ │ │ │ └── filters - │ │ │ │ └── (b1:64 = 5) OR ((b1:64 IS DISTINCT FROM CAST(NULL AS INT8)) OR CAST(NULL AS BOOL)) [outer=(64), constraints=(/64: (/NULL - ]; tight)] - │ │ │ └── aggregations - │ │ │ ├── const-agg [as=b1:29, outer=(29)] - │ │ │ │ └── b1:29 - │ │ │ ├── const-agg [as=b2:30, outer=(30)] - │ │ │ │ └── b2:30 - │ │ │ ├── const-agg [as=b3:31, outer=(31)] - │ │ │ │ └── b3:31 - │ │ │ └── const-agg [as=b4:32, outer=(32)] - │ │ │ └── b4:32 - │ │ └── filters (true) - │ └── project + │ │ ├── fd: ()-->(29), (33)-->(30-32), (40)-->(36-39) + │ │ └── distinct-on + │ │ ├── columns: b1:29!null b2:30!null b3:31 b4:32 b.rowid:33!null d1:36!null d2:37 d3:38 d4:39 d.rowid:40!null + │ │ ├── grouping columns: b.rowid:33!null d.rowid:40!null + │ │ ├── key: (33,40) + │ │ ├── fd: (33,40)-->(29-32,36-39) + │ │ ├── union-all + │ │ │ ├── columns: b1:29!null b2:30!null b3:31 b4:32 b.rowid:33!null d1:36!null d2:37 d3:38 d4:39 d.rowid:40!null + │ │ │ ├── left columns: b1:57 b2:58 b3:59 b4:60 b.rowid:61 d1:64 d2:65 d3:66 d4:67 d.rowid:68 + │ │ │ ├── right columns: b1:71 b2:72 b3:73 b4:74 b.rowid:75 d1:78 d2:79 d3:80 d4:81 d.rowid:82 + │ │ │ ├── inner-join (lookup d@d) + │ │ │ │ ├── columns: b1:57!null b2:58!null b3:59 b4:60 b.rowid:61!null d1:64!null d2:65 d3:66 d4:67 d.rowid:68!null + │ │ │ │ ├── key columns: [58] = [64] + │ │ │ │ ├── key: (61,68) + │ │ │ │ ├── fd: ()-->(57), (61)-->(58-60), (68)-->(64-67), (58)==(64), (64)==(58) + │ │ │ │ ├── scan b@b_b1_b2_idx + │ │ │ │ │ ├── columns: b1:57!null b2:58!null b3:59 b4:60 b.rowid:61!null + │ │ │ │ │ ├── constraint: /57/58/61: (/0/NULL - /0] + │ │ │ │ │ ├── key: (61) + │ │ │ │ │ └── fd: ()-->(57), (61)-->(58-60) + │ │ │ │ └── filters + │ │ │ │ └── ((d1:64 IS DISTINCT FROM CAST(NULL AS INT8)) OR CAST(NULL AS BOOL)) OR (d1:64 = 5) [outer=(64), constraints=(/64: (/NULL - ]; tight)] + │ │ │ └── inner-join (lookup d@d) + │ │ │ ├── columns: b1:71!null b2:72!null b3:73 b4:74 b.rowid:75!null d1:78!null d2:79 d3:80 d4:81 d.rowid:82!null + │ │ │ ├── key columns: [71] = [78] + │ │ │ ├── key: (75,82) + │ │ │ ├── fd: ()-->(71,78), (75)-->(72-74), (82)-->(79-81), (71)==(78), (78)==(71) + │ │ │ ├── scan b@b_b1_b2_idx + │ │ │ │ ├── columns: b1:71!null b2:72!null b3:73 b4:74 b.rowid:75!null + │ │ │ │ ├── constraint: /71/72/75 + │ │ │ │ │ ├── [/0/0 - /0/0] + │ │ │ │ │ └── [/0/5 - /0/5] + │ │ │ │ ├── key: (75) + │ │ │ │ └── fd: ()-->(71), (75)-->(72-74) + │ │ │ └── filters (true) + │ │ └── aggregations + │ │ ├── const-agg [as=b1:29, outer=(29)] + │ │ │ └── b1:29 + │ │ ├── const-agg [as=b2:30, outer=(30)] + │ │ │ └── b2:30 + │ │ ├── const-agg [as=b3:31, outer=(31)] + │ │ │ └── b3:31 + │ │ ├── const-agg [as=b4:32, outer=(32)] + │ │ │ └── b4:32 + │ │ ├── const-agg [as=d1:36, outer=(36)] + │ │ │ └── d1:36 + │ │ ├── const-agg [as=d2:37, outer=(37)] + │ │ │ └── d2:37 + │ │ ├── const-agg [as=d3:38, outer=(38)] + │ │ │ └── d3:38 + │ │ └── const-agg [as=d4:39, outer=(39)] + │ │ └── d4:39 + │ └── inner-join (lookup d@d) │ ├── columns: b1:43!null b2:44!null b3:45 b4:46 b.rowid:47!null d1:50!null d2:51 d3:52 d4:53 d.rowid:54!null + │ ├── key columns: [43] = [50] │ ├── key: (47,54) - │ ├── fd: ()-->(43), (47)-->(44-46), (54)-->(50-53) - │ └── distinct-on - │ ├── columns: b1:43!null b2:44!null b3:45 b4:46 b.rowid:47!null d1:50!null d2:51 d3:52 d4:53 d.rowid:54!null - │ ├── grouping columns: b.rowid:47!null d.rowid:54!null - │ ├── key: (47,54) - │ ├── fd: (47,54)-->(43-46,50-53) - │ ├── union-all - │ │ ├── columns: b1:43!null b2:44!null b3:45 b4:46 b.rowid:47!null d1:50!null d2:51 d3:52 d4:53 d.rowid:54!null - │ │ ├── left columns: b1:71 b2:72 b3:73 b4:74 b.rowid:75 d1:78 d2:79 d3:80 d4:81 d.rowid:82 - │ │ ├── right columns: b1:85 b2:86 b3:87 b4:88 b.rowid:89 d1:92 d2:93 d3:94 d4:95 d.rowid:96 - │ │ ├── inner-join (lookup d@d) - │ │ │ ├── columns: b1:71!null b2:72!null b3:73 b4:74 b.rowid:75!null d1:78!null d2:79 d3:80 d4:81 d.rowid:82!null - │ │ │ ├── key columns: [72] = [78] - │ │ │ ├── key: (75,82) - │ │ │ ├── fd: ()-->(71), (75)-->(72-74), (82)-->(78-81), (72)==(78), (78)==(72) - │ │ │ ├── scan b@b_b1_b2_idx - │ │ │ │ ├── columns: b1:71!null b2:72!null b3:73 b4:74 b.rowid:75!null - │ │ │ │ ├── constraint: /71/72/75: (/0/NULL - /0] - │ │ │ │ ├── key: (75) - │ │ │ │ └── fd: ()-->(71), (75)-->(72-74) - │ │ │ └── filters - │ │ │ └── ((d1:78 IS DISTINCT FROM CAST(NULL AS INT8)) OR CAST(NULL AS BOOL)) OR (d1:78 = 5) [outer=(78), constraints=(/78: (/NULL - ]; tight)] - │ │ └── inner-join (lookup d@d) - │ │ ├── columns: b1:85!null b2:86!null b3:87 b4:88 b.rowid:89!null d1:92!null d2:93 d3:94 d4:95 d.rowid:96!null - │ │ ├── key columns: [85] = [92] - │ │ ├── key: (89,96) - │ │ ├── fd: ()-->(85,92), (89)-->(86-88), (96)-->(93-95), (85)==(92), (92)==(85) - │ │ ├── scan b@b_b1_b2_idx - │ │ │ ├── columns: b1:85!null b2:86!null b3:87 b4:88 b.rowid:89!null - │ │ │ ├── constraint: /85/86/89 - │ │ │ │ ├── [/0/0 - /0/0] - │ │ │ │ └── [/0/5 - /0/5] - │ │ │ ├── key: (89) - │ │ │ └── fd: ()-->(85), (89)-->(86-88) - │ │ └── filters (true) - │ └── aggregations - │ ├── const-agg [as=b1:43, outer=(43)] - │ │ └── b1:43 - │ ├── const-agg [as=b2:44, outer=(44)] - │ │ └── b2:44 - │ ├── const-agg [as=b3:45, outer=(45)] - │ │ └── b3:45 - │ ├── const-agg [as=b4:46, outer=(46)] - │ │ └── b4:46 - │ ├── const-agg [as=d1:50, outer=(50)] - │ │ └── d1:50 - │ ├── const-agg [as=d2:51, outer=(51)] - │ │ └── d2:51 - │ ├── const-agg [as=d3:52, outer=(52)] - │ │ └── d3:52 - │ └── const-agg [as=d4:53, outer=(53)] - │ └── d4:53 + │ ├── fd: (47)-->(43-46), (54)-->(50-53), (43)==(50), (50)==(43) + │ ├── distinct-on + │ │ ├── columns: b1:43!null b2:44!null b3:45 b4:46 b.rowid:47!null + │ │ ├── grouping columns: b.rowid:47!null + │ │ ├── key: (47) + │ │ ├── fd: (47)-->(43-46) + │ │ ├── union-all + │ │ │ ├── columns: b1:43!null b2:44!null b3:45 b4:46 b.rowid:47!null + │ │ │ ├── left columns: b1:115 b2:116 b3:117 b4:118 b.rowid:119 + │ │ │ ├── right columns: b1:122 b2:123 b3:124 b4:125 b.rowid:126 + │ │ │ ├── scan b@b_b1_b2_idx + │ │ │ │ ├── columns: b1:115!null b2:116!null b3:117 b4:118 b.rowid:119!null + │ │ │ │ ├── constraint: /115/116/119 + │ │ │ │ │ ├── [/0/0 - /0/0] + │ │ │ │ │ └── [/0/5 - /0/5] + │ │ │ │ ├── key: (119) + │ │ │ │ └── fd: ()-->(115), (119)-->(116-118) + │ │ │ └── select + │ │ │ ├── columns: b1:122!null b2:123!null b3:124 b4:125 b.rowid:126!null + │ │ │ ├── key: (126) + │ │ │ ├── fd: ()-->(123), (126)-->(122,124,125) + │ │ │ ├── scan b@b_b2_idx + │ │ │ │ ├── columns: b1:122 b2:123!null b3:124 b4:125 b.rowid:126!null + │ │ │ │ ├── constraint: /123/126: [/5 - /5] + │ │ │ │ ├── key: (126) + │ │ │ │ └── fd: ()-->(123), (126)-->(122,124,125) + │ │ │ └── filters + │ │ │ └── (b1:122 = 5) OR ((b1:122 IS DISTINCT FROM CAST(NULL AS INT8)) OR CAST(NULL AS BOOL)) [outer=(122), constraints=(/122: (/NULL - ]; tight)] + │ │ └── aggregations + │ │ ├── const-agg [as=b1:43, outer=(43)] + │ │ │ └── b1:43 + │ │ ├── const-agg [as=b2:44, outer=(44)] + │ │ │ └── b2:44 + │ │ ├── const-agg [as=b3:45, outer=(45)] + │ │ │ └── b3:45 + │ │ └── const-agg [as=b4:46, outer=(46)] + │ │ └── b4:46 + │ └── filters (true) └── aggregations ├── const-agg [as=b1:1, outer=(1)] │ └── b1:1 @@ -690,6 +715,222 @@ project └── const-agg [as=d4:10, outer=(10)] └── d4:10 +# Same test as above, but with the order of variables in equality conditions +# swapped. +opt expect=SplitDisjunctionOfJoinTerms +SELECT * FROM a, d WHERE (d2 = a1 AND d1 = a2) OR (d4 = a3 AND d3 = a4) +---- +project + ├── columns: a1:1!null a2:2!null a3:3!null a4:4!null d1:7 d2:8 d3:9 d4:10 + └── distinct-on + ├── columns: a1:1!null a2:2!null a3:3!null a4:4!null d1:7 d2:8 d3:9 d4:10 rowid:11!null + ├── grouping columns: a1:1!null a2:2!null a3:3!null a4:4!null rowid:11!null + ├── key: (1-4,11) + ├── fd: (1-4,11)-->(7-10) + ├── union-all + │ ├── columns: a1:1!null a2:2!null a3:3!null a4:4!null d1:7 d2:8 d3:9 d4:10 rowid:11!null + │ ├── left columns: a1:14 a2:15 a3:16 a4:17 d1:20 d2:21 d3:22 d4:23 rowid:24 + │ ├── right columns: a1:27 a2:28 a3:29 a4:30 d1:33 d2:34 d3:35 d4:36 rowid:37 + │ ├── inner-join (hash) + │ │ ├── columns: a1:14!null a2:15!null a3:16!null a4:17!null d1:20!null d2:21!null d3:22 d4:23 rowid:24!null + │ │ ├── key: (16,17,24) + │ │ ├── fd: (24)-->(20-23), (14)==(21), (21)==(14), (15)==(20), (20)==(15) + │ │ ├── scan a + │ │ │ ├── columns: a1:14!null a2:15!null a3:16!null a4:17!null + │ │ │ └── key: (14-17) + │ │ ├── scan d + │ │ │ ├── columns: d1:20 d2:21 d3:22 d4:23 rowid:24!null + │ │ │ ├── key: (24) + │ │ │ └── fd: (24)-->(20-23) + │ │ └── filters + │ │ ├── d2:21 = a1:14 [outer=(14,21), constraints=(/14: (/NULL - ]; /21: (/NULL - ]), fd=(14)==(21), (21)==(14)] + │ │ └── d1:20 = a2:15 [outer=(15,20), constraints=(/15: (/NULL - ]; /20: (/NULL - ]), fd=(15)==(20), (20)==(15)] + │ └── inner-join (hash) + │ ├── columns: a1:27!null a2:28!null a3:29!null a4:30!null d1:33 d2:34 d3:35!null d4:36!null rowid:37!null + │ ├── key: (27,28,37) + │ ├── fd: (37)-->(33-36), (29)==(36), (36)==(29), (30)==(35), (35)==(30) + │ ├── scan a + │ │ ├── columns: a1:27!null a2:28!null a3:29!null a4:30!null + │ │ └── key: (27-30) + │ ├── scan d + │ │ ├── columns: d1:33 d2:34 d3:35 d4:36 rowid:37!null + │ │ ├── key: (37) + │ │ └── fd: (37)-->(33-36) + │ └── filters + │ ├── d4:36 = a3:29 [outer=(29,36), constraints=(/29: (/NULL - ]; /36: (/NULL - ]), fd=(29)==(36), (36)==(29)] + │ └── d3:35 = a4:30 [outer=(30,35), constraints=(/30: (/NULL - ]; /35: (/NULL - ]), fd=(30)==(35), (35)==(30)] + └── aggregations + ├── const-agg [as=d1:7, outer=(7)] + │ └── d1:7 + ├── const-agg [as=d2:8, outer=(8)] + │ └── d2:8 + ├── const-agg [as=d3:9, outer=(9)] + │ └── d3:9 + └── const-agg [as=d4:10, outer=(10)] + └── d4:10 + +# We should be able to split the disjunction even though the predicates are +# equalities but not equijoin expressions. +opt expect=SplitDisjunctionOfJoinTerms +SELECT e.* +FROM + e + INNER JOIN f ON f.f3 = e.e2 +WHERE + e.e5 = 30 + OR (e.e3 = 10 AND f.f2 = 20) +---- +project + ├── columns: e1:1!null e2:2!null e3:3!null e4:4!null e5:5 + ├── fd: (1)-->(2-5) + └── project + ├── columns: e1:1!null e2:2!null e3:3!null e4:4!null e5:5 f2:9 f3:10!null + ├── fd: (1)-->(2-5), (2)==(10), (10)==(2) + └── distinct-on + ├── columns: e1:1!null e2:2!null e3:3!null e4:4!null e5:5 f1:8!null f2:9 f3:10!null + ├── grouping columns: e1:1!null f1:8!null + ├── key: (1,8) + ├── fd: (2)==(10), (10)==(2), (1,8)-->(2-5,9,10) + ├── union-all + │ ├── columns: e1:1!null e2:2!null e3:3!null e4:4!null e5:5 f1:8!null f2:9 f3:10!null + │ ├── left columns: e1:14 e2:15 e3:16 e4:17 e5:18 f1:21 f2:22 f3:23 + │ ├── right columns: e1:27 e2:28 e3:29 e4:30 e5:31 f1:34 f2:35 f3:36 + │ ├── fd: (2)==(10), (10)==(2) + │ ├── inner-join (lookup f) + │ │ ├── columns: e1:14!null e2:15!null e3:16!null e4:17!null e5:18!null f1:21!null f2:22 f3:23!null + │ │ ├── key columns: [21] = [21] + │ │ ├── lookup columns are key + │ │ ├── key: (14,21) + │ │ ├── fd: ()-->(18), (14)-->(15-17), (21)-->(22,23), (15)==(23), (23)==(15) + │ │ ├── inner-join (lookup f@f_f3_idx) + │ │ │ ├── columns: e1:14!null e2:15!null e3:16!null e4:17!null e5:18!null f1:21!null f3:23!null + │ │ │ ├── key columns: [15] = [23] + │ │ │ ├── key: (14,21) + │ │ │ ├── fd: ()-->(18), (14)-->(15-17), (21)-->(23), (15)==(23), (23)==(15) + │ │ │ ├── index-join e + │ │ │ │ ├── columns: e1:14!null e2:15!null e3:16!null e4:17!null e5:18!null + │ │ │ │ ├── key: (14) + │ │ │ │ ├── fd: ()-->(18), (14)-->(15-17) + │ │ │ │ └── scan e@e_e5_idx + │ │ │ │ ├── columns: e1:14!null e5:18!null + │ │ │ │ ├── constraint: /18/14: [/30 - /30] + │ │ │ │ ├── key: (14) + │ │ │ │ └── fd: ()-->(18) + │ │ │ └── filters (true) + │ │ └── filters (true) + │ └── inner-join (hash) + │ ├── columns: e1:27!null e2:28!null e3:29!null e4:30!null e5:31 f1:34!null f2:35!null f3:36!null + │ ├── key: (27,34) + │ ├── fd: ()-->(29,35), (27)-->(28,30,31), (34)-->(36), (28)==(36), (36)==(28) + │ ├── index-join e + │ │ ├── columns: e1:27!null e2:28!null e3:29!null e4:30!null e5:31 + │ │ ├── key: (27) + │ │ ├── fd: ()-->(29), (27)-->(28,30,31) + │ │ └── scan e@e_e3_e5_e4_idx + │ │ ├── columns: e1:27!null e3:29!null e4:30!null e5:31 + │ │ ├── constraint: /29/31/30/27: [/10 - /10] + │ │ ├── key: (27) + │ │ └── fd: ()-->(29), (27)-->(30,31) + │ ├── scan f@f_f2_idx + │ │ ├── columns: f1:34!null f2:35!null f3:36 + │ │ ├── constraint: /35/34: [/20 - /20] + │ │ ├── key: (34) + │ │ └── fd: ()-->(35), (34)-->(36) + │ └── filters + │ └── f3:36 = e2:28 [outer=(28,36), constraints=(/28: (/NULL - ]; /36: (/NULL - ]), fd=(28)==(36), (36)==(28)] + └── aggregations + ├── const-agg [as=e2:2, outer=(2)] + │ └── e2:2 + ├── const-agg [as=e3:3, outer=(3)] + │ └── e3:3 + ├── const-agg [as=e4:4, outer=(4)] + │ └── e4:4 + ├── const-agg [as=e5:5, outer=(5)] + │ └── e5:5 + ├── const-agg [as=f2:9, outer=(9)] + │ └── f2:9 + └── const-agg [as=f3:10, outer=(10)] + └── f3:10 + +# We should be able to split the disjunction even though the predicates are +# not equalities. +opt expect=SplitDisjunctionOfJoinTerms +SELECT e.* +FROM + e + INNER JOIN f ON f.f3 = e.e2 +WHERE + (e.e5 > 30 AND e.e5 < 40) + OR (e.e4 IN ('a', 'b') AND f.f2 < 20 AND f.f2 > 10) +---- +project + ├── columns: e1:1!null e2:2!null e3:3!null e4:4!null e5:5 + ├── fd: (1)-->(2-5) + └── project + ├── columns: e1:1!null e2:2!null e3:3!null e4:4!null e5:5 f2:9 f3:10!null + ├── fd: (1)-->(2-5), (2)==(10), (10)==(2) + └── distinct-on + ├── columns: e1:1!null e2:2!null e3:3!null e4:4!null e5:5 f1:8!null f2:9 f3:10!null + ├── grouping columns: e1:1!null f1:8!null + ├── key: (1,8) + ├── fd: (2)==(10), (10)==(2), (1,8)-->(2-5,9,10) + ├── union-all + │ ├── columns: e1:1!null e2:2!null e3:3!null e4:4!null e5:5 f1:8!null f2:9 f3:10!null + │ ├── left columns: e1:14 e2:15 e3:16 e4:17 e5:18 f1:21 f2:22 f3:23 + │ ├── right columns: e1:27 e2:28 e3:29 e4:30 e5:31 f1:34 f2:35 f3:36 + │ ├── fd: (2)==(10), (10)==(2) + │ ├── inner-join (hash) + │ │ ├── columns: e1:14!null e2:15!null e3:16!null e4:17!null e5:18!null f1:21!null f2:22 f3:23!null + │ │ ├── key: (14,21) + │ │ ├── fd: (14)-->(15-18), (21)-->(22,23), (15)==(23), (23)==(15) + │ │ ├── scan f@f_f2_idx + │ │ │ ├── columns: f1:21!null f2:22 f3:23 + │ │ │ ├── key: (21) + │ │ │ └── fd: (21)-->(22,23) + │ │ ├── index-join e + │ │ │ ├── columns: e1:14!null e2:15!null e3:16!null e4:17!null e5:18!null + │ │ │ ├── key: (14) + │ │ │ ├── fd: (14)-->(15-18) + │ │ │ └── scan e@e_e5_idx + │ │ │ ├── columns: e1:14!null e5:18!null + │ │ │ ├── constraint: /18/14: [/31 - /39] + │ │ │ ├── key: (14) + │ │ │ └── fd: (14)-->(18) + │ │ └── filters + │ │ └── f3:23 = e2:15 [outer=(15,23), constraints=(/15: (/NULL - ]; /23: (/NULL - ]), fd=(15)==(23), (23)==(15)] + │ └── inner-join (hash) + │ ├── columns: e1:27!null e2:28!null e3:29!null e4:30!null e5:31 f1:34!null f2:35!null f3:36!null + │ ├── key: (27,34) + │ ├── fd: (27)-->(28-31), (34)-->(35,36), (28)==(36), (36)==(28) + │ ├── scan f@f_f2_idx + │ │ ├── columns: f1:34!null f2:35!null f3:36 + │ │ ├── constraint: /35/34: [/11 - /19] + │ │ ├── key: (34) + │ │ └── fd: (34)-->(35,36) + │ ├── index-join e + │ │ ├── columns: e1:27!null e2:28!null e3:29!null e4:30!null e5:31 + │ │ ├── key: (27) + │ │ ├── fd: (27)-->(28-31) + │ │ └── scan e@e_e3_idx,partial + │ │ ├── columns: e1:27!null e3:29!null + │ │ ├── key: (27) + │ │ └── fd: (27)-->(29) + │ └── filters + │ └── f3:36 = e2:28 [outer=(28,36), constraints=(/28: (/NULL - ]; /36: (/NULL - ]), fd=(28)==(36), (36)==(28)] + └── aggregations + ├── const-agg [as=e2:2, outer=(2)] + │ └── e2:2 + ├── const-agg [as=e3:3, outer=(3)] + │ └── e3:3 + ├── const-agg [as=e4:4, outer=(4)] + │ └── e4:4 + ├── const-agg [as=e5:5, outer=(5)] + │ └── e5:5 + ├── const-agg [as=f2:9, outer=(9)] + │ └── f2:9 + └── const-agg [as=f3:10, outer=(10)] + └── f3:10 + ######################### # Uncorrelated semijoin # ######################### @@ -730,7 +971,7 @@ select │ └── true [as=column15:15] └── false -opt expect-not=SplitDisjunctionOfJoinTerms +opt expect=SplitDisjunctionOfJoinTerms SELECT * FROM a WHERE EXISTS (SELECT 1 FROM c, d WHERE d1 = 4 OR c2 = 50 HAVING sum(d4) > 40) ---- select @@ -760,14 +1001,55 @@ select │ │ │ ├── cardinality: [1 - 1] │ │ │ ├── key: () │ │ │ ├── fd: ()-->(21) - │ │ │ ├── inner-join (cross) - │ │ │ │ ├── columns: c2:8 d1:14 d4:17 - │ │ │ │ ├── scan c - │ │ │ │ │ └── columns: c2:8 - │ │ │ │ ├── scan d - │ │ │ │ │ └── columns: d1:14 d4:17 - │ │ │ │ └── filters - │ │ │ │ └── (d1:14 = 4) OR (c2:8 = 50) [outer=(8,14)] + │ │ │ ├── distinct-on + │ │ │ │ ├── columns: c2:8 c.rowid:11!null d1:14 d4:17 d.rowid:18!null + │ │ │ │ ├── grouping columns: c.rowid:11!null d.rowid:18!null + │ │ │ │ ├── key: (11,18) + │ │ │ │ ├── fd: (11,18)-->(8,14,17) + │ │ │ │ ├── union-all + │ │ │ │ │ ├── columns: c2:8 c.rowid:11!null d1:14 d4:17 d.rowid:18!null + │ │ │ │ │ ├── left columns: c2:25 c.rowid:28 d1:31 d4:34 d.rowid:35 + │ │ │ │ │ ├── right columns: c2:39 c.rowid:42 d1:45 d4:48 d.rowid:49 + │ │ │ │ │ ├── inner-join (cross) + │ │ │ │ │ │ ├── columns: c2:25 c.rowid:28!null d1:31!null d4:34 d.rowid:35!null + │ │ │ │ │ │ ├── key: (28,35) + │ │ │ │ │ │ ├── fd: ()-->(31), (28)-->(25), (35)-->(34) + │ │ │ │ │ │ ├── scan c + │ │ │ │ │ │ │ ├── columns: c2:25 c.rowid:28!null + │ │ │ │ │ │ │ ├── key: (28) + │ │ │ │ │ │ │ └── fd: (28)-->(25) + │ │ │ │ │ │ ├── scan d@d + │ │ │ │ │ │ │ ├── columns: d1:31!null d4:34 d.rowid:35!null + │ │ │ │ │ │ │ ├── constraint: /31/35: [/4 - /4] + │ │ │ │ │ │ │ ├── key: (35) + │ │ │ │ │ │ │ └── fd: ()-->(31), (35)-->(34) + │ │ │ │ │ │ └── filters (true) + │ │ │ │ │ └── inner-join (cross) + │ │ │ │ │ ├── columns: c2:39!null c.rowid:42!null d1:45 d4:48 d.rowid:49!null + │ │ │ │ │ ├── key: (42,49) + │ │ │ │ │ ├── fd: ()-->(39), (49)-->(45,48) + │ │ │ │ │ ├── scan d + │ │ │ │ │ │ ├── columns: d1:45 d4:48 d.rowid:49!null + │ │ │ │ │ │ ├── key: (49) + │ │ │ │ │ │ └── fd: (49)-->(45,48) + │ │ │ │ │ ├── select + │ │ │ │ │ │ ├── columns: c2:39!null c.rowid:42!null + │ │ │ │ │ │ ├── key: (42) + │ │ │ │ │ │ ├── fd: ()-->(39) + │ │ │ │ │ │ ├── scan c + │ │ │ │ │ │ │ ├── columns: c2:39 c.rowid:42!null + │ │ │ │ │ │ │ ├── key: (42) + │ │ │ │ │ │ │ └── fd: (42)-->(39) + │ │ │ │ │ │ └── filters + │ │ │ │ │ │ └── c2:39 = 50 [outer=(39), constraints=(/39: [/50 - /50]; tight), fd=()-->(39)] + │ │ │ │ │ └── filters (true) + │ │ │ │ └── aggregations + │ │ │ │ ├── const-agg [as=c2:8, outer=(8)] + │ │ │ │ │ └── c2:8 + │ │ │ │ ├── const-agg [as=d1:14, outer=(14)] + │ │ │ │ │ └── d1:14 + │ │ │ │ └── const-agg [as=d4:17, outer=(17)] + │ │ │ │ └── d4:17 │ │ │ └── aggregations │ │ │ └── sum [as=sum:21, outer=(17)] │ │ │ └── d4:17 @@ -1070,39 +1352,39 @@ project │ │ ├── columns: c1:7 c.rowid:11!null d1:14 d.rowid:18!null │ │ ├── left columns: c1:34 c.rowid:38 d1:41 d.rowid:45 │ │ ├── right columns: c1:48 c.rowid:52 d1:55 d.rowid:59 - │ │ ├── inner-join (hash) - │ │ │ ├── columns: c1:34!null c.rowid:38!null d1:41!null d.rowid:45!null + │ │ ├── inner-join (cross) + │ │ │ ├── columns: c1:34 c.rowid:38!null d1:41 d.rowid:45!null │ │ │ ├── key: (38,45) - │ │ │ ├── fd: (38)-->(34), (45)-->(41), (34)==(41), (41)==(34) - │ │ │ ├── scan c - │ │ │ │ ├── columns: c1:34 c.rowid:38!null - │ │ │ │ ├── key: (38) - │ │ │ │ └── fd: (38)-->(34) + │ │ │ ├── fd: ()-->(34), (45)-->(41) │ │ │ ├── scan d │ │ │ │ ├── columns: d1:41 d.rowid:45!null │ │ │ │ ├── key: (45) │ │ │ │ └── fd: (45)-->(41) - │ │ │ └── filters - │ │ │ └── c1:34 = d1:41 [outer=(34,41), constraints=(/34: (/NULL - ]; /41: (/NULL - ]), fd=(34)==(41), (41)==(34)] - │ │ └── inner-join (cross) - │ │ ├── columns: c1:48 c.rowid:52!null d1:55 d.rowid:59!null + │ │ │ ├── select + │ │ │ │ ├── columns: c1:34 c.rowid:38!null + │ │ │ │ ├── key: (38) + │ │ │ │ ├── fd: ()-->(34) + │ │ │ │ ├── scan c + │ │ │ │ │ ├── columns: c1:34 c.rowid:38!null + │ │ │ │ │ ├── key: (38) + │ │ │ │ │ └── fd: (38)-->(34) + │ │ │ │ └── filters + │ │ │ │ └── c1:34 IS NULL [outer=(34), constraints=(/34: [/NULL - /NULL]; tight), fd=()-->(34)] + │ │ │ └── filters (true) + │ │ └── inner-join (hash) + │ │ ├── columns: c1:48!null c.rowid:52!null d1:55!null d.rowid:59!null │ │ ├── key: (52,59) - │ │ ├── fd: ()-->(48), (59)-->(55) + │ │ ├── fd: (52)-->(48), (59)-->(55), (48)==(55), (55)==(48) + │ │ ├── scan c + │ │ │ ├── columns: c1:48 c.rowid:52!null + │ │ │ ├── key: (52) + │ │ │ └── fd: (52)-->(48) │ │ ├── scan d │ │ │ ├── columns: d1:55 d.rowid:59!null │ │ │ ├── key: (59) │ │ │ └── fd: (59)-->(55) - │ │ ├── select - │ │ │ ├── columns: c1:48 c.rowid:52!null - │ │ │ ├── key: (52) - │ │ │ ├── fd: ()-->(48) - │ │ │ ├── scan c - │ │ │ │ ├── columns: c1:48 c.rowid:52!null - │ │ │ │ ├── key: (52) - │ │ │ │ └── fd: (52)-->(48) - │ │ │ └── filters - │ │ │ └── c1:48 IS NULL [outer=(48), constraints=(/48: [/NULL - /NULL]; tight), fd=()-->(48)] - │ │ └── filters (true) + │ │ └── filters + │ │ └── c1:48 = d1:55 [outer=(48,55), constraints=(/48: (/NULL - ]; /55: (/NULL - ]), fd=(48)==(55), (55)==(48)] │ └── aggregations │ ├── const-agg [as=c1:7, outer=(7)] │ │ └── c1:7 @@ -1138,39 +1420,39 @@ anti-join (cross) │ │ ├── columns: c1:8 c.rowid:12!null d1:15 d.rowid:19!null │ │ ├── left columns: c1:22 c.rowid:26 d1:29 d.rowid:33 │ │ ├── right columns: c1:36 c.rowid:40 d1:43 d.rowid:47 - │ │ ├── inner-join (hash) - │ │ │ ├── columns: c1:22!null c.rowid:26!null d1:29!null d.rowid:33!null + │ │ ├── inner-join (cross) + │ │ │ ├── columns: c1:22 c.rowid:26!null d1:29 d.rowid:33!null │ │ │ ├── key: (26,33) - │ │ │ ├── fd: (26)-->(22), (33)-->(29), (22)==(29), (29)==(22) - │ │ │ ├── scan c - │ │ │ │ ├── columns: c1:22 c.rowid:26!null - │ │ │ │ ├── key: (26) - │ │ │ │ └── fd: (26)-->(22) + │ │ │ ├── fd: ()-->(22), (33)-->(29) │ │ │ ├── scan d │ │ │ │ ├── columns: d1:29 d.rowid:33!null │ │ │ │ ├── key: (33) │ │ │ │ └── fd: (33)-->(29) - │ │ │ └── filters - │ │ │ └── c1:22 = d1:29 [outer=(22,29), constraints=(/22: (/NULL - ]; /29: (/NULL - ]), fd=(22)==(29), (29)==(22)] - │ │ └── inner-join (cross) - │ │ ├── columns: c1:36 c.rowid:40!null d1:43 d.rowid:47!null + │ │ │ ├── select + │ │ │ │ ├── columns: c1:22 c.rowid:26!null + │ │ │ │ ├── key: (26) + │ │ │ │ ├── fd: ()-->(22) + │ │ │ │ ├── scan c + │ │ │ │ │ ├── columns: c1:22 c.rowid:26!null + │ │ │ │ │ ├── key: (26) + │ │ │ │ │ └── fd: (26)-->(22) + │ │ │ │ └── filters + │ │ │ │ └── c1:22 IS NULL [outer=(22), constraints=(/22: [/NULL - /NULL]; tight), fd=()-->(22)] + │ │ │ └── filters (true) + │ │ └── inner-join (hash) + │ │ ├── columns: c1:36!null c.rowid:40!null d1:43!null d.rowid:47!null │ │ ├── key: (40,47) - │ │ ├── fd: ()-->(36), (47)-->(43) + │ │ ├── fd: (40)-->(36), (47)-->(43), (36)==(43), (43)==(36) + │ │ ├── scan c + │ │ │ ├── columns: c1:36 c.rowid:40!null + │ │ │ ├── key: (40) + │ │ │ └── fd: (40)-->(36) │ │ ├── scan d │ │ │ ├── columns: d1:43 d.rowid:47!null │ │ │ ├── key: (47) │ │ │ └── fd: (47)-->(43) - │ │ ├── select - │ │ │ ├── columns: c1:36 c.rowid:40!null - │ │ │ ├── key: (40) - │ │ │ ├── fd: ()-->(36) - │ │ │ ├── scan c - │ │ │ │ ├── columns: c1:36 c.rowid:40!null - │ │ │ │ ├── key: (40) - │ │ │ │ └── fd: (40)-->(36) - │ │ │ └── filters - │ │ │ └── c1:36 IS NULL [outer=(36), constraints=(/36: [/NULL - /NULL]; tight), fd=()-->(36)] - │ │ └── filters (true) + │ │ └── filters + │ │ └── c1:36 = d1:43 [outer=(36,43), constraints=(/36: (/NULL - ]; /43: (/NULL - ]), fd=(36)==(43), (43)==(36)] │ └── aggregations │ ├── const-agg [as=c1:8, outer=(8)] │ │ └── c1:8 @@ -1200,39 +1482,39 @@ anti-join (cross) │ │ │ ├── columns: c1:8 c2:9 c.rowid:12!null d1:15 d.rowid:19!null │ │ │ ├── left columns: c1:23 c2:24 c.rowid:27 d1:30 d.rowid:34 │ │ │ ├── right columns: c1:37 c2:38 c.rowid:41 d1:44 d.rowid:48 - │ │ │ ├── inner-join (hash) - │ │ │ │ ├── columns: c1:23!null c2:24 c.rowid:27!null d1:30!null d.rowid:34!null + │ │ │ ├── inner-join (cross) + │ │ │ │ ├── columns: c1:23 c2:24 c.rowid:27!null d1:30 d.rowid:34!null │ │ │ │ ├── key: (27,34) - │ │ │ │ ├── fd: (27)-->(23,24), (34)-->(30), (23)==(30), (30)==(23) - │ │ │ │ ├── scan c - │ │ │ │ │ ├── columns: c1:23 c2:24 c.rowid:27!null - │ │ │ │ │ ├── key: (27) - │ │ │ │ │ └── fd: (27)-->(23,24) + │ │ │ │ ├── fd: ()-->(23), (27)-->(24), (34)-->(30) │ │ │ │ ├── scan d │ │ │ │ │ ├── columns: d1:30 d.rowid:34!null │ │ │ │ │ ├── key: (34) │ │ │ │ │ └── fd: (34)-->(30) - │ │ │ │ └── filters - │ │ │ │ └── c1:23 = d1:30 [outer=(23,30), constraints=(/23: (/NULL - ]; /30: (/NULL - ]), fd=(23)==(30), (30)==(23)] - │ │ │ └── inner-join (cross) - │ │ │ ├── columns: c1:37 c2:38 c.rowid:41!null d1:44 d.rowid:48!null + │ │ │ │ ├── select + │ │ │ │ │ ├── columns: c1:23 c2:24 c.rowid:27!null + │ │ │ │ │ ├── key: (27) + │ │ │ │ │ ├── fd: ()-->(23), (27)-->(24) + │ │ │ │ │ ├── scan c + │ │ │ │ │ │ ├── columns: c1:23 c2:24 c.rowid:27!null + │ │ │ │ │ │ ├── key: (27) + │ │ │ │ │ │ └── fd: (27)-->(23,24) + │ │ │ │ │ └── filters + │ │ │ │ │ └── c1:23 IS NULL [outer=(23), constraints=(/23: [/NULL - /NULL]; tight), fd=()-->(23)] + │ │ │ │ └── filters (true) + │ │ │ └── inner-join (hash) + │ │ │ ├── columns: c1:37!null c2:38 c.rowid:41!null d1:44!null d.rowid:48!null │ │ │ ├── key: (41,48) - │ │ │ ├── fd: ()-->(37), (41)-->(38), (48)-->(44) + │ │ │ ├── fd: (41)-->(37,38), (48)-->(44), (37)==(44), (44)==(37) + │ │ │ ├── scan c + │ │ │ │ ├── columns: c1:37 c2:38 c.rowid:41!null + │ │ │ │ ├── key: (41) + │ │ │ │ └── fd: (41)-->(37,38) │ │ │ ├── scan d │ │ │ │ ├── columns: d1:44 d.rowid:48!null │ │ │ │ ├── key: (48) │ │ │ │ └── fd: (48)-->(44) - │ │ │ ├── select - │ │ │ │ ├── columns: c1:37 c2:38 c.rowid:41!null - │ │ │ │ ├── key: (41) - │ │ │ │ ├── fd: ()-->(37), (41)-->(38) - │ │ │ │ ├── scan c - │ │ │ │ │ ├── columns: c1:37 c2:38 c.rowid:41!null - │ │ │ │ │ ├── key: (41) - │ │ │ │ │ └── fd: (41)-->(37,38) - │ │ │ │ └── filters - │ │ │ │ └── c1:37 IS NULL [outer=(37), constraints=(/37: [/NULL - /NULL]; tight), fd=()-->(37)] - │ │ │ └── filters (true) + │ │ │ └── filters + │ │ │ └── c1:37 = d1:44 [outer=(37,44), constraints=(/37: (/NULL - ]; /44: (/NULL - ]), fd=(37)==(44), (44)==(37)] │ │ └── aggregations │ │ ├── const-agg [as=c1:8, outer=(8)] │ │ │ └── c1:8 @@ -1308,7 +1590,7 @@ select │ └── true [as=column15:15] └── false -opt expect-not=SplitDisjunctionOfJoinTerms +opt expect=SplitDisjunctionOfJoinTerms SELECT * FROM a WHERE NOT EXISTS (SELECT 1 FROM c, d WHERE d1 = 4 OR c2 = 50 or d2+c3 > 5) ---- select @@ -1650,39 +1932,39 @@ anti-join (cross) │ │ │ ├── columns: c1:7 c.rowid:11!null d1:14 d.rowid:18!null │ │ │ ├── left columns: c1:22 c.rowid:26 d1:29 d.rowid:33 │ │ │ ├── right columns: c1:36 c.rowid:40 d1:43 d.rowid:47 - │ │ │ ├── inner-join (hash) - │ │ │ │ ├── columns: c1:22!null c.rowid:26!null d1:29!null d.rowid:33!null + │ │ │ ├── inner-join (cross) + │ │ │ │ ├── columns: c1:22 c.rowid:26!null d1:29 d.rowid:33!null │ │ │ │ ├── key: (26,33) - │ │ │ │ ├── fd: (26)-->(22), (33)-->(29), (22)==(29), (29)==(22) - │ │ │ │ ├── scan c - │ │ │ │ │ ├── columns: c1:22 c.rowid:26!null - │ │ │ │ │ ├── key: (26) - │ │ │ │ │ └── fd: (26)-->(22) + │ │ │ │ ├── fd: ()-->(22), (33)-->(29) │ │ │ │ ├── scan d │ │ │ │ │ ├── columns: d1:29 d.rowid:33!null │ │ │ │ │ ├── key: (33) │ │ │ │ │ └── fd: (33)-->(29) - │ │ │ │ └── filters - │ │ │ │ └── c1:22 = d1:29 [outer=(22,29), constraints=(/22: (/NULL - ]; /29: (/NULL - ]), fd=(22)==(29), (29)==(22)] - │ │ │ └── inner-join (cross) - │ │ │ ├── columns: c1:36 c.rowid:40!null d1:43 d.rowid:47!null + │ │ │ │ ├── select + │ │ │ │ │ ├── columns: c1:22 c.rowid:26!null + │ │ │ │ │ ├── key: (26) + │ │ │ │ │ ├── fd: ()-->(22) + │ │ │ │ │ ├── scan c + │ │ │ │ │ │ ├── columns: c1:22 c.rowid:26!null + │ │ │ │ │ │ ├── key: (26) + │ │ │ │ │ │ └── fd: (26)-->(22) + │ │ │ │ │ └── filters + │ │ │ │ │ └── c1:22 IS NULL [outer=(22), constraints=(/22: [/NULL - /NULL]; tight), fd=()-->(22)] + │ │ │ │ └── filters (true) + │ │ │ └── inner-join (hash) + │ │ │ ├── columns: c1:36!null c.rowid:40!null d1:43!null d.rowid:47!null │ │ │ ├── key: (40,47) - │ │ │ ├── fd: ()-->(36), (47)-->(43) + │ │ │ ├── fd: (40)-->(36), (47)-->(43), (36)==(43), (43)==(36) + │ │ │ ├── scan c + │ │ │ │ ├── columns: c1:36 c.rowid:40!null + │ │ │ │ ├── key: (40) + │ │ │ │ └── fd: (40)-->(36) │ │ │ ├── scan d │ │ │ │ ├── columns: d1:43 d.rowid:47!null │ │ │ │ ├── key: (47) │ │ │ │ └── fd: (47)-->(43) - │ │ │ ├── select - │ │ │ │ ├── columns: c1:36 c.rowid:40!null - │ │ │ │ ├── key: (40) - │ │ │ │ ├── fd: ()-->(36) - │ │ │ │ ├── scan c - │ │ │ │ │ ├── columns: c1:36 c.rowid:40!null - │ │ │ │ │ ├── key: (40) - │ │ │ │ │ └── fd: (40)-->(36) - │ │ │ │ └── filters - │ │ │ │ └── c1:36 IS NULL [outer=(36), constraints=(/36: [/NULL - /NULL]; tight), fd=()-->(36)] - │ │ │ └── filters (true) + │ │ │ └── filters + │ │ │ └── c1:36 = d1:43 [outer=(36,43), constraints=(/36: (/NULL - ]; /43: (/NULL - ]), fd=(36)==(43), (43)==(36)] │ │ └── aggregations │ │ ├── const-agg [as=c1:7, outer=(7)] │ │ │ └── c1:7 @@ -2194,23 +2476,35 @@ project │ │ │ │ ├── columns: b1:23 b2:24 b3:25 b.rowid:27!null │ │ │ │ ├── key: (27) │ │ │ │ ├── fd: (27)-->(23-25) - │ │ │ │ └── inner-join (hash) - │ │ │ │ ├── columns: b1:23 b2:24!null b3:25 b.rowid:27!null c2:31!null - │ │ │ │ ├── multiplicity: left-rows(zero-or-one), right-rows(zero-or-more) + │ │ │ │ └── project + │ │ │ │ ├── columns: b1:23 b2:24 b3:25 b.rowid:27!null │ │ │ │ ├── key: (27) - │ │ │ │ ├── fd: (27)-->(23-25), (24)==(31), (31)==(24) - │ │ │ │ ├── scan b - │ │ │ │ │ ├── columns: b1:23 b2:24 b3:25 b.rowid:27!null - │ │ │ │ │ ├── key: (27) - │ │ │ │ │ └── fd: (27)-->(23-25) - │ │ │ │ ├── distinct-on - │ │ │ │ │ ├── columns: c2:31 - │ │ │ │ │ ├── grouping columns: c2:31 - │ │ │ │ │ ├── key: (31) - │ │ │ │ │ └── scan c - │ │ │ │ │ └── columns: c2:31 - │ │ │ │ └── filters - │ │ │ │ └── c2:31 = b2:24 [outer=(24,31), constraints=(/24: (/NULL - ]; /31: (/NULL - ]), fd=(24)==(31), (31)==(24)] + │ │ │ │ ├── fd: (27)-->(23-25) + │ │ │ │ └── inner-join (cross) + │ │ │ │ ├── columns: b1:23 b2:24 b3:25 b.rowid:27!null c2:31 + │ │ │ │ ├── multiplicity: left-rows(zero-or-one), right-rows(zero-or-more) + │ │ │ │ ├── key: (27) + │ │ │ │ ├── fd: ()-->(31), (27)-->(23-25) + │ │ │ │ ├── scan b + │ │ │ │ │ ├── columns: b1:23 b2:24 b3:25 b.rowid:27!null + │ │ │ │ │ ├── key: (27) + │ │ │ │ │ └── fd: (27)-->(23-25) + │ │ │ │ ├── limit + │ │ │ │ │ ├── columns: c2:31 + │ │ │ │ │ ├── cardinality: [0 - 1] + │ │ │ │ │ ├── key: () + │ │ │ │ │ ├── fd: ()-->(31) + │ │ │ │ │ ├── select + │ │ │ │ │ │ ├── columns: c2:31 + │ │ │ │ │ │ ├── fd: ()-->(31) + │ │ │ │ │ │ ├── limit hint: 1.00 + │ │ │ │ │ │ ├── scan c + │ │ │ │ │ │ │ ├── columns: c2:31 + │ │ │ │ │ │ │ └── limit hint: 100.00 + │ │ │ │ │ │ └── filters + │ │ │ │ │ │ └── c2:31 IS NULL [outer=(31), constraints=(/31: [/NULL - /NULL]; tight), fd=()-->(31)] + │ │ │ │ │ └── 1 + │ │ │ │ └── filters (true) │ │ │ └── project │ │ │ ├── columns: b1:37 b2:38 b3:39 b.rowid:41!null │ │ │ ├── key: (41) @@ -2249,35 +2543,23 @@ project │ │ │ │ ├── columns: b1:205 b2:206 b3:207 b.rowid:209!null │ │ │ │ ├── key: (209) │ │ │ │ ├── fd: (209)-->(205-207) - │ │ │ │ └── project - │ │ │ │ ├── columns: b1:205 b2:206 b3:207 b.rowid:209!null + │ │ │ │ └── inner-join (hash) + │ │ │ │ ├── columns: b1:205 b2:206!null b3:207 b.rowid:209!null c2:213!null + │ │ │ │ ├── multiplicity: left-rows(zero-or-one), right-rows(zero-or-more) │ │ │ │ ├── key: (209) - │ │ │ │ ├── fd: (209)-->(205-207) - │ │ │ │ └── inner-join (cross) - │ │ │ │ ├── columns: b1:205 b2:206 b3:207 b.rowid:209!null c2:213 - │ │ │ │ ├── multiplicity: left-rows(zero-or-one), right-rows(zero-or-more) - │ │ │ │ ├── key: (209) - │ │ │ │ ├── fd: ()-->(213), (209)-->(205-207) - │ │ │ │ ├── scan b - │ │ │ │ │ ├── columns: b1:205 b2:206 b3:207 b.rowid:209!null - │ │ │ │ │ ├── key: (209) - │ │ │ │ │ └── fd: (209)-->(205-207) - │ │ │ │ ├── limit - │ │ │ │ │ ├── columns: c2:213 - │ │ │ │ │ ├── cardinality: [0 - 1] - │ │ │ │ │ ├── key: () - │ │ │ │ │ ├── fd: ()-->(213) - │ │ │ │ │ ├── select - │ │ │ │ │ │ ├── columns: c2:213 - │ │ │ │ │ │ ├── fd: ()-->(213) - │ │ │ │ │ │ ├── limit hint: 1.00 - │ │ │ │ │ │ ├── scan c - │ │ │ │ │ │ │ ├── columns: c2:213 - │ │ │ │ │ │ │ └── limit hint: 100.00 - │ │ │ │ │ │ └── filters - │ │ │ │ │ │ └── c2:213 IS NULL [outer=(213), constraints=(/213: [/NULL - /NULL]; tight), fd=()-->(213)] - │ │ │ │ │ └── 1 - │ │ │ │ └── filters (true) + │ │ │ │ ├── fd: (209)-->(205-207), (206)==(213), (213)==(206) + │ │ │ │ ├── scan b + │ │ │ │ │ ├── columns: b1:205 b2:206 b3:207 b.rowid:209!null + │ │ │ │ │ ├── key: (209) + │ │ │ │ │ └── fd: (209)-->(205-207) + │ │ │ │ ├── distinct-on + │ │ │ │ │ ├── columns: c2:213 + │ │ │ │ │ ├── grouping columns: c2:213 + │ │ │ │ │ ├── key: (213) + │ │ │ │ │ └── scan c + │ │ │ │ │ └── columns: c2:213 + │ │ │ │ └── filters + │ │ │ │ └── c2:213 = b2:206 [outer=(206,213), constraints=(/206: (/NULL - ]; /213: (/NULL - ]), fd=(206)==(213), (213)==(206)] │ │ │ └── aggregations │ │ │ ├── const-agg [as=b1:37, outer=(37)] │ │ │ │ └── b1:37 @@ -2324,23 +2606,35 @@ project │ │ │ │ ├── columns: b1:24 b2:25 b3:26 b.rowid:28!null │ │ │ │ ├── key: (28) │ │ │ │ ├── fd: (28)-->(24-26) - │ │ │ │ └── inner-join (hash) - │ │ │ │ ├── columns: b1:24 b2:25!null b3:26 b.rowid:28!null c2:32!null - │ │ │ │ ├── multiplicity: left-rows(zero-or-one), right-rows(zero-or-more) + │ │ │ │ └── project + │ │ │ │ ├── columns: b1:24 b2:25 b3:26 b.rowid:28!null │ │ │ │ ├── key: (28) - │ │ │ │ ├── fd: (28)-->(24-26), (25)==(32), (32)==(25) - │ │ │ │ ├── scan b - │ │ │ │ │ ├── columns: b1:24 b2:25 b3:26 b.rowid:28!null - │ │ │ │ │ ├── key: (28) - │ │ │ │ │ └── fd: (28)-->(24-26) - │ │ │ │ ├── distinct-on - │ │ │ │ │ ├── columns: c2:32 - │ │ │ │ │ ├── grouping columns: c2:32 - │ │ │ │ │ ├── key: (32) - │ │ │ │ │ └── scan c - │ │ │ │ │ └── columns: c2:32 - │ │ │ │ └── filters - │ │ │ │ └── c2:32 = b2:25 [outer=(25,32), constraints=(/25: (/NULL - ]; /32: (/NULL - ]), fd=(25)==(32), (32)==(25)] + │ │ │ │ ├── fd: (28)-->(24-26) + │ │ │ │ └── inner-join (cross) + │ │ │ │ ├── columns: b1:24 b2:25 b3:26 b.rowid:28!null c2:32 + │ │ │ │ ├── multiplicity: left-rows(zero-or-one), right-rows(zero-or-more) + │ │ │ │ ├── key: (28) + │ │ │ │ ├── fd: ()-->(32), (28)-->(24-26) + │ │ │ │ ├── scan b + │ │ │ │ │ ├── columns: b1:24 b2:25 b3:26 b.rowid:28!null + │ │ │ │ │ ├── key: (28) + │ │ │ │ │ └── fd: (28)-->(24-26) + │ │ │ │ ├── limit + │ │ │ │ │ ├── columns: c2:32 + │ │ │ │ │ ├── cardinality: [0 - 1] + │ │ │ │ │ ├── key: () + │ │ │ │ │ ├── fd: ()-->(32) + │ │ │ │ │ ├── select + │ │ │ │ │ │ ├── columns: c2:32 + │ │ │ │ │ │ ├── fd: ()-->(32) + │ │ │ │ │ │ ├── limit hint: 1.00 + │ │ │ │ │ │ ├── scan c + │ │ │ │ │ │ │ ├── columns: c2:32 + │ │ │ │ │ │ │ └── limit hint: 100.00 + │ │ │ │ │ │ └── filters + │ │ │ │ │ │ └── c2:32 IS NULL [outer=(32), constraints=(/32: [/NULL - /NULL]; tight), fd=()-->(32)] + │ │ │ │ │ └── 1 + │ │ │ │ └── filters (true) │ │ │ └── project │ │ │ ├── columns: b1:38 b2:39 b3:40 b.rowid:42!null │ │ │ ├── key: (42) @@ -2379,35 +2673,23 @@ project │ │ │ │ ├── columns: b1:206 b2:207 b3:208 b.rowid:210!null │ │ │ │ ├── key: (210) │ │ │ │ ├── fd: (210)-->(206-208) - │ │ │ │ └── project - │ │ │ │ ├── columns: b1:206 b2:207 b3:208 b.rowid:210!null + │ │ │ │ └── inner-join (hash) + │ │ │ │ ├── columns: b1:206 b2:207!null b3:208 b.rowid:210!null c2:214!null + │ │ │ │ ├── multiplicity: left-rows(zero-or-one), right-rows(zero-or-more) │ │ │ │ ├── key: (210) - │ │ │ │ ├── fd: (210)-->(206-208) - │ │ │ │ └── inner-join (cross) - │ │ │ │ ├── columns: b1:206 b2:207 b3:208 b.rowid:210!null c2:214 - │ │ │ │ ├── multiplicity: left-rows(zero-or-one), right-rows(zero-or-more) - │ │ │ │ ├── key: (210) - │ │ │ │ ├── fd: ()-->(214), (210)-->(206-208) - │ │ │ │ ├── scan b - │ │ │ │ │ ├── columns: b1:206 b2:207 b3:208 b.rowid:210!null - │ │ │ │ │ ├── key: (210) - │ │ │ │ │ └── fd: (210)-->(206-208) - │ │ │ │ ├── limit - │ │ │ │ │ ├── columns: c2:214 - │ │ │ │ │ ├── cardinality: [0 - 1] - │ │ │ │ │ ├── key: () - │ │ │ │ │ ├── fd: ()-->(214) - │ │ │ │ │ ├── select - │ │ │ │ │ │ ├── columns: c2:214 - │ │ │ │ │ │ ├── fd: ()-->(214) - │ │ │ │ │ │ ├── limit hint: 1.00 - │ │ │ │ │ │ ├── scan c - │ │ │ │ │ │ │ ├── columns: c2:214 - │ │ │ │ │ │ │ └── limit hint: 100.00 - │ │ │ │ │ │ └── filters - │ │ │ │ │ │ └── c2:214 IS NULL [outer=(214), constraints=(/214: [/NULL - /NULL]; tight), fd=()-->(214)] - │ │ │ │ │ └── 1 - │ │ │ │ └── filters (true) + │ │ │ │ ├── fd: (210)-->(206-208), (207)==(214), (214)==(207) + │ │ │ │ ├── scan b + │ │ │ │ │ ├── columns: b1:206 b2:207 b3:208 b.rowid:210!null + │ │ │ │ │ ├── key: (210) + │ │ │ │ │ └── fd: (210)-->(206-208) + │ │ │ │ ├── distinct-on + │ │ │ │ │ ├── columns: c2:214 + │ │ │ │ │ ├── grouping columns: c2:214 + │ │ │ │ │ ├── key: (214) + │ │ │ │ │ └── scan c + │ │ │ │ │ └── columns: c2:214 + │ │ │ │ └── filters + │ │ │ │ └── c2:214 = b2:207 [outer=(207,214), constraints=(/207: (/NULL - ]; /214: (/NULL - ]), fd=(207)==(214), (214)==(207)] │ │ │ └── aggregations │ │ │ ├── const-agg [as=b1:38, outer=(38)] │ │ │ │ └── b1:38 @@ -3025,6 +3307,161 @@ inner-join (hash) └── filters └── a1:1 = b1:7 [outer=(1,7), constraints=(/1: (/NULL - ]; /7: (/NULL - ]), fd=(1)==(7), (7)==(1)] +# We should be able to split the disjunction even though the predicates are +# equalities but not equijoin expressions. +opt expect=SplitDisjunctionOfJoinTerms +SELECT + e.* +FROM + e +WHERE EXISTS ( + SELECT * + FROM f + WHERE (e5 = 30 OR (e3 = 10 AND f2 = 20)) AND f3 = e2 +); +---- +project + ├── columns: e1:1!null e2:2!null e3:3!null e4:4!null e5:5 + ├── key: (1) + ├── fd: (1)-->(2-5) + └── distinct-on + ├── columns: e1:1!null e2:2!null e3:3!null e4:4!null e5:5 + ├── grouping columns: e1:1!null + ├── key: (1) + ├── fd: (1)-->(2-5) + ├── union-all + │ ├── columns: e1:1!null e2:2!null e3:3!null e4:4!null e5:5 + │ ├── left columns: e1:14 e2:15 e3:16 e4:17 e5:18 + │ ├── right columns: e1:27 e2:28 e3:29 e4:30 e5:31 + │ ├── semi-join (lookup f@f_f3_idx) + │ │ ├── columns: e1:14!null e2:15!null e3:16!null e4:17!null e5:18!null + │ │ ├── key columns: [15] = [23] + │ │ ├── key: (14) + │ │ ├── fd: ()-->(18), (14)-->(15-17) + │ │ ├── index-join e + │ │ │ ├── columns: e1:14!null e2:15!null e3:16!null e4:17!null e5:18!null + │ │ │ ├── key: (14) + │ │ │ ├── fd: ()-->(18), (14)-->(15-17) + │ │ │ └── scan e@e_e5_idx + │ │ │ ├── columns: e1:14!null e5:18!null + │ │ │ ├── constraint: /18/14: [/30 - /30] + │ │ │ ├── key: (14) + │ │ │ └── fd: ()-->(18) + │ │ └── filters (true) + │ └── semi-join (hash) + │ ├── columns: e1:27!null e2:28!null e3:29!null e4:30!null e5:31 + │ ├── key: (27) + │ ├── fd: ()-->(29), (27)-->(28,30,31) + │ ├── index-join e + │ │ ├── columns: e1:27!null e2:28!null e3:29!null e4:30!null e5:31 + │ │ ├── key: (27) + │ │ ├── fd: ()-->(29), (27)-->(28,30,31) + │ │ └── scan e@e_e3_e5_e4_idx + │ │ ├── columns: e1:27!null e3:29!null e4:30!null e5:31 + │ │ ├── constraint: /29/31/30/27: [/10 - /10] + │ │ ├── key: (27) + │ │ └── fd: ()-->(29), (27)-->(30,31) + │ ├── scan f@f_f2_idx + │ │ ├── columns: f2:35!null f3:36 + │ │ ├── constraint: /35/34: [/20 - /20] + │ │ └── fd: ()-->(35) + │ └── filters + │ └── f3:36 = e2:28 [outer=(28,36), constraints=(/28: (/NULL - ]; /36: (/NULL - ]), fd=(28)==(36), (36)==(28)] + └── aggregations + ├── const-agg [as=e2:2, outer=(2)] + │ └── e2:2 + ├── const-agg [as=e3:3, outer=(3)] + │ └── e3:3 + ├── const-agg [as=e4:4, outer=(4)] + │ └── e4:4 + └── const-agg [as=e5:5, outer=(5)] + └── e5:5 + +# We should be able to split the disjunction even though the predicates are +# not equalities. +opt expect=SplitDisjunctionOfJoinTerms +SELECT + e.* +FROM + e +WHERE EXISTS ( + SELECT * + FROM f + WHERE ( + (e.e5 > 30 AND e.e5 < 40) + OR (e.e4 IN ('a', 'b') AND f.f2 < 20 AND f.f2 > 10) + ) AND f3 = e2 +) +---- +project + ├── columns: e1:1!null e2:2!null e3:3!null e4:4!null e5:5 + ├── key: (1) + ├── fd: (1)-->(2-5) + └── distinct-on + ├── columns: e1:1!null e2:2!null e3:3!null e4:4!null e5:5 + ├── grouping columns: e1:1!null + ├── key: (1) + ├── fd: (1)-->(2-5) + ├── union-all + │ ├── columns: e1:1!null e2:2!null e3:3!null e4:4!null e5:5 + │ ├── left columns: e1:14 e2:15 e3:16 e4:17 e5:18 + │ ├── right columns: e1:27 e2:28 e3:29 e4:30 e5:31 + │ ├── project + │ │ ├── columns: e1:14!null e2:15!null e3:16!null e4:17!null e5:18!null + │ │ ├── key: (14) + │ │ ├── fd: (14)-->(15-18) + │ │ └── inner-join (hash) + │ │ ├── columns: e1:14!null e2:15!null e3:16!null e4:17!null e5:18!null f3:23!null + │ │ ├── multiplicity: left-rows(zero-or-more), right-rows(zero-or-one) + │ │ ├── key: (14) + │ │ ├── fd: (14)-->(15-18), (15)==(23), (23)==(15) + │ │ ├── distinct-on + │ │ │ ├── columns: f3:23 + │ │ │ ├── grouping columns: f3:23 + │ │ │ ├── internal-ordering: +23 + │ │ │ ├── key: (23) + │ │ │ └── scan f@f_f3_idx + │ │ │ ├── columns: f3:23 + │ │ │ └── ordering: +23 + │ │ ├── index-join e + │ │ │ ├── columns: e1:14!null e2:15!null e3:16!null e4:17!null e5:18!null + │ │ │ ├── key: (14) + │ │ │ ├── fd: (14)-->(15-18) + │ │ │ └── scan e@e_e5_idx + │ │ │ ├── columns: e1:14!null e5:18!null + │ │ │ ├── constraint: /18/14: [/31 - /39] + │ │ │ ├── key: (14) + │ │ │ └── fd: (14)-->(18) + │ │ └── filters + │ │ └── f3:23 = e2:15 [outer=(15,23), constraints=(/15: (/NULL - ]; /23: (/NULL - ]), fd=(15)==(23), (23)==(15)] + │ └── semi-join (hash) + │ ├── columns: e1:27!null e2:28!null e3:29!null e4:30!null e5:31 + │ ├── key: (27) + │ ├── fd: (27)-->(28-31) + │ ├── index-join e + │ │ ├── columns: e1:27!null e2:28!null e3:29!null e4:30!null e5:31 + │ │ ├── key: (27) + │ │ ├── fd: (27)-->(28-31) + │ │ └── scan e@e_e3_idx,partial + │ │ ├── columns: e1:27!null e3:29!null + │ │ ├── key: (27) + │ │ └── fd: (27)-->(29) + │ ├── scan f@f_f2_idx + │ │ ├── columns: f2:35!null f3:36 + │ │ └── constraint: /35/34: [/11 - /19] + │ └── filters + │ └── f3:36 = e2:28 [outer=(28,36), constraints=(/28: (/NULL - ]; /36: (/NULL - ]), fd=(28)==(36), (36)==(28)] + └── aggregations + ├── const-agg [as=e2:2, outer=(2)] + │ └── e2:2 + ├── const-agg [as=e3:3, outer=(3)] + │ └── e3:3 + ├── const-agg [as=e4:4, outer=(4)] + │ └── e4:4 + └── const-agg [as=e5:5, outer=(5)] + └── e5:5 + + ####################### # Correlated antijoin # ####################### @@ -3469,6 +3906,73 @@ inner-join (lookup a) │ └── c2:44 = b2:37 [outer=(37,44), constraints=(/37: (/NULL - ]; /44: (/NULL - ]), fd=(37)==(44), (44)==(37)] └── filters (true) +# We should be able to split the disjunction even though the predicates are +# equalities but not equijoin expressions. +# TODO(rytaft): investigate whether bad stats are causing us to select the +# wrong plan. +opt expect=SplitDisjunctionOfAntiJoinTerms +SELECT + e.* +FROM + e +WHERE NOT EXISTS ( + SELECT * + FROM f + WHERE ((e5 = 30 AND f2 = 40) OR (e3 = 10 AND f2 = 20)) AND f3 = e2 +); +---- +anti-join (hash) + ├── columns: e1:1!null e2:2!null e3:3!null e4:4!null e5:5 + ├── key: (1) + ├── fd: (1)-->(2-5) + ├── scan e + │ ├── columns: e1:1!null e2:2!null e3:3!null e4:4!null e5:5 + │ ├── partial index predicates + │ │ └── e_e3_idx: filters + │ │ └── e4:4 IN ('a', 'b') [outer=(4), constraints=(/4: [/'a' - /'a'] [/'b' - /'b']; tight)] + │ ├── key: (1) + │ └── fd: (1)-->(2-5) + ├── scan f@f_f2_idx + │ └── columns: f2:9 f3:10 + └── filters + ├── ((e5:5 = 30) AND (f2:9 = 40)) OR ((e3:3 = 10) AND (f2:9 = 20)) [outer=(3,5,9), constraints=(/9: [/20 - /20] [/40 - /40])] + └── f3:10 = e2:2 [outer=(2,10), constraints=(/2: (/NULL - ]; /10: (/NULL - ]), fd=(2)==(10), (10)==(2)] + +# We should be able to split the disjunction even though the predicates are +# not equalities. +# TODO(rytaft): investigate whether bad stats are causing us to select the +# wrong plan. +opt expect=SplitDisjunctionOfAntiJoinTerms +SELECT + e.* +FROM + e +WHERE NOT EXISTS ( + SELECT * + FROM f + WHERE ( + (e.e5 > 30 AND e.e5 < 40) + OR (e.e4 IN ('a', 'b') AND f.f2 < 20 AND f.f2 > 10) + ) AND f3 = e2 +) +---- +anti-join (hash) + ├── columns: e1:1!null e2:2!null e3:3!null e4:4!null e5:5 + ├── key: (1) + ├── fd: (1)-->(2-5) + ├── scan e + │ ├── columns: e1:1!null e2:2!null e3:3!null e4:4!null e5:5 + │ ├── partial index predicates + │ │ └── e_e3_idx: filters + │ │ └── e4:4 IN ('a', 'b') [outer=(4), constraints=(/4: [/'a' - /'a'] [/'b' - /'b']; tight)] + │ ├── key: (1) + │ └── fd: (1)-->(2-5) + ├── scan f@f_f2_idx + │ └── columns: f2:9 f3:10 + └── filters + ├── ((e5:5 > 30) AND (e5:5 < 40)) OR (((e4:4 IN ('a', 'b')) AND (f2:9 < 20)) AND (f2:9 > 10)) [outer=(4,5,9)] + └── f3:10 = e2:2 [outer=(2,10), constraints=(/2: (/NULL - ]; /10: (/NULL - ]), fd=(2)==(10), (10)==(2)] + # NOT IN subquery opt expect=SplitDisjunctionOfJoinTerms SELECT d3,d1,d2 FROM d WHERE d1 NOT IN (SELECT b1 FROM b WHERE EXISTS (SELECT 1 FROM c WHERE c2=b2 OR c2=b3)) @@ -3635,28 +4139,85 @@ inner-join (cross) └── filters └── (((t1.a1:1 = t2.a1:7) OR (t1.a1:1 = t2.a2:8)) AND (t1.a2:2 = t2.a2:8)) OR (((t2.a1:7 = (t1.a1:1 + 1)) OR (t2.a2:8 = (t1.a1:1 + 4))) AND ((t2.a2:8 = (t1.a2:2 + 8)) OR (t2.a2:8 = (t1.a2:2 + 9)))) [outer=(1,2,7,8), immutable, constraints=(/8: (/NULL - ])] -# Negative Tests -# No equijoin terms. Must be at least one equality predicate referencing -# columns from both tables. -opt expect-not=SplitDisjunctionOfJoinTerms -SELECT * FROM a t1, a t2 WHERE (t1.a2 = 1 OR t2.a2 = 1) +# We can split the disjunction here even if the setting +# optimizer_use_improved_split_disjunction_for_joins is false, since we +# don't require bare variables on either side of the join equalities. +opt expect=SplitDisjunctionOfJoinTerms set=optimizer_use_improved_split_disjunction_for_joins=false +SELECT * FROM a t1, a t2 WHERE (t1.a2 = t2.a2+1 OR t1.a3 = t2.a3+1) AND (t1.a1 = t2.a1+1 OR t1.a4 = t2.a4+1) ---- -inner-join (cross) +project ├── columns: a1:1!null a2:2!null a3:3!null a4:4!null a1:7!null a2:8!null a3:9!null a4:10!null + ├── immutable ├── key: (1-4,7-10) - ├── scan a [as=t1] - │ ├── columns: t1.a1:1!null t1.a2:2!null t1.a3:3!null t1.a4:4!null - │ └── key: (1-4) - ├── scan a [as=t2] - │ ├── columns: t2.a1:7!null t2.a2:8!null t2.a3:9!null t2.a4:10!null - │ └── key: (7-10) - └── filters - └── (t1.a2:2 = 1) OR (t2.a2:8 = 1) [outer=(2,8)] + └── distinct-on + ├── columns: t1.a1:1!null t1.a2:2!null t1.a3:3!null t1.a4:4!null t2.a1:7!null t2.a2:8!null t2.a3:9!null t2.a4:10!null + ├── grouping columns: t1.a1:1!null t1.a2:2!null t1.a3:3!null t1.a4:4!null t2.a1:7!null t2.a2:8!null t2.a3:9!null t2.a4:10!null + ├── immutable + ├── key: (1-4,7-10) + └── union-all + ├── columns: t1.a1:1!null t1.a2:2!null t1.a3:3!null t1.a4:4!null t2.a1:7!null t2.a2:8!null t2.a3:9!null t2.a4:10!null + ├── left columns: t1.a1:13 t1.a2:14 t1.a3:15 t1.a4:16 t2.a1:19 t2.a2:20 t2.a3:21 t2.a4:22 + ├── right columns: t1.a1:25 t1.a2:26 t1.a3:27 t1.a4:28 t2.a1:31 t2.a2:32 t2.a3:33 t2.a4:34 + ├── immutable + ├── project + │ ├── columns: t1.a1:13!null t1.a2:14!null t1.a3:15!null t1.a4:16!null t2.a1:19!null t2.a2:20!null t2.a3:21!null t2.a4:22!null + │ ├── immutable + │ ├── key: (13,15,16,19-22) + │ ├── fd: (20)-->(14) + │ └── inner-join (hash) + │ ├── columns: t1.a1:13!null t1.a2:14!null t1.a3:15!null t1.a4:16!null t2.a1:19!null t2.a2:20!null t2.a3:21!null t2.a4:22!null column37:37!null + │ ├── immutable + │ ├── key: (13,15,16,19-22) + │ ├── fd: (20)-->(37), (14)==(37), (37)==(14) + │ ├── scan a [as=t1] + │ │ ├── columns: t1.a1:13!null t1.a2:14!null t1.a3:15!null t1.a4:16!null + │ │ └── key: (13-16) + │ ├── project + │ │ ├── columns: column37:37!null t2.a1:19!null t2.a2:20!null t2.a3:21!null t2.a4:22!null + │ │ ├── immutable + │ │ ├── key: (19-22) + │ │ ├── fd: (20)-->(37) + │ │ ├── scan a [as=t2] + │ │ │ ├── columns: t2.a1:19!null t2.a2:20!null t2.a3:21!null t2.a4:22!null + │ │ │ └── key: (19-22) + │ │ └── projections + │ │ └── t2.a2:20 + 1 [as=column37:37, outer=(20), immutable] + │ └── filters + │ ├── (t1.a1:13 = (t2.a1:19 + 1)) OR (t1.a4:16 = (t2.a4:22 + 1)) [outer=(13,16,19,22), immutable] + │ └── t1.a2:14 = column37:37 [outer=(14,37), constraints=(/14: (/NULL - ]; /37: (/NULL - ]), fd=(14)==(37), (37)==(14)] + └── project + ├── columns: t1.a1:25!null t1.a2:26!null t1.a3:27!null t1.a4:28!null t2.a1:31!null t2.a2:32!null t2.a3:33!null t2.a4:34!null + ├── immutable + ├── key: (25,26,28,31-34) + ├── fd: (33)-->(27) + └── inner-join (hash) + ├── columns: t1.a1:25!null t1.a2:26!null t1.a3:27!null t1.a4:28!null t2.a1:31!null t2.a2:32!null t2.a3:33!null t2.a4:34!null column38:38!null + ├── immutable + ├── key: (25,26,28,31-34) + ├── fd: (33)-->(38), (27)==(38), (38)==(27) + ├── scan a [as=t1] + │ ├── columns: t1.a1:25!null t1.a2:26!null t1.a3:27!null t1.a4:28!null + │ └── key: (25-28) + ├── project + │ ├── columns: column38:38!null t2.a1:31!null t2.a2:32!null t2.a3:33!null t2.a4:34!null + │ ├── immutable + │ ├── key: (31-34) + │ ├── fd: (33)-->(38) + │ ├── scan a [as=t2] + │ │ ├── columns: t2.a1:31!null t2.a2:32!null t2.a3:33!null t2.a4:34!null + │ │ └── key: (31-34) + │ └── projections + │ └── t2.a3:33 + 1 [as=column38:38, outer=(33), immutable] + └── filters + ├── (t1.a1:25 = (t2.a1:31 + 1)) OR (t1.a4:28 = (t2.a4:34 + 1)) [outer=(25,28,31,34), immutable] + └── t1.a3:27 = column38:38 [outer=(27,38), constraints=(/27: (/NULL - ]; /38: (/NULL - ]), fd=(27)==(38), (38)==(27)] -# No equijoin terms. Must be at least one equality predicate referencing -# columns from both tables. -opt expect-not=SplitDisjunctionOfJoinTerms -SELECT * FROM a t1, a t2 WHERE (t1.a2 > t2.a2 AND t1.a3 > t2.a3 OR t2.a2 = 1) +# Negative Tests. +# No interesting terms. Must be at least one equality predicate referencing +# columns from both tables if optimizer_use_improved_split_disjunction_for_joins +# is false. +opt expect-not=SplitDisjunctionOfJoinTerms set=optimizer_use_improved_split_disjunction_for_joins=false +SELECT * FROM a t1, a t2 WHERE (t1.a2 > t2.a2 AND t1.a3 > t2.a3 OR t2.a2 = 2) ---- inner-join (cross) ├── columns: a1:1!null a2:2!null a3:3!null a4:4!null a1:7!null a2:8!null a3:9!null a4:10!null @@ -3668,7 +4229,7 @@ inner-join (cross) │ ├── columns: t2.a1:7!null t2.a2:8!null t2.a3:9!null t2.a4:10!null │ └── key: (7-10) └── filters - └── ((t1.a2:2 > t2.a2:8) AND (t1.a3:3 > t2.a3:9)) OR (t2.a2:8 = 1) [outer=(2,3,8,9), constraints=(/8: (/NULL - ])] + └── ((t1.a2:2 > t2.a2:8) AND (t1.a3:3 > t2.a3:9)) OR (t2.a2:8 = 2) [outer=(2,3,8,9), constraints=(/8: (/NULL - ])] # Outer join not supported with this optimization opt expect-not=SplitDisjunctionOfJoinTerms @@ -3818,10 +4379,11 @@ project └── t1.a2:2 # The conjuncts under the top-level disjunct contain no equijoin terms, and -# neither do the nested simple predicates. -opt expect-not=SplitDisjunctionOfJoinTerms -SELECT * FROM a t1, a t2 WHERE (((t1.a1 > t1.a1 OR t1.a1 <= t1.a2) AND (t1.a2 > t2.a2+1 OR t1.a1 <= t1.a2-1)) OR - ((t1.a1 > t1.a1+5 OR t1.a1 <= t1.a2+5) AND (t1.a2 > t2.a2+7 OR t1.a1 <= t1.a2-9))) +# neither do the nested simple predicates. The rule does not fire in this +# case if optimizer_use_improved_split_disjunction_for_joins is false. +opt expect-not=SplitDisjunctionOfJoinTerms set=optimizer_use_improved_split_disjunction_for_joins=false +SELECT * FROM a t1, a t2 WHERE (((t1.a1 > t2.a1 OR t1.a1 <= t2.a2) AND (t1.a2 > t2.a2+1 OR t1.a1 <= t2.a2-1)) OR + ((t1.a1 > t2.a1+5 OR t1.a1 <= t2.a2+5) AND (t1.a2 > t2.a2+7 OR t1.a1 <= t2.a2-9))) ---- inner-join (cross) ├── columns: a1:1!null a2:2!null a3:3!null a4:4!null a1:7!null a2:8!null a3:9!null a4:10!null @@ -3834,10 +4396,10 @@ inner-join (cross) │ ├── columns: t2.a1:7!null t2.a2:8!null t2.a3:9!null t2.a4:10!null │ └── key: (7-10) └── filters - └── ((((t1.a1:1 IS NOT DISTINCT FROM CAST(NULL AS INT8)) AND CAST(NULL AS BOOL)) OR (t1.a1:1 <= t1.a2:2)) AND ((t1.a2:2 > (t2.a2:8 + 1)) OR (t1.a1:1 <= (t1.a2:2 - 1)))) OR (((t1.a1:1 > (t1.a1:1 + 5)) OR (t1.a1:1 <= (t1.a2:2 + 5))) AND ((t1.a2:2 > (t2.a2:8 + 7)) OR (t1.a1:1 <= (t1.a2:2 - 9)))) [outer=(1,2,8), immutable, constraints=(/1: (/NULL - ])] + └── (((t1.a1:1 > t2.a1:7) OR (t1.a1:1 <= t2.a2:8)) AND ((t1.a2:2 > (t2.a2:8 + 1)) OR (t1.a1:1 <= (t2.a2:8 - 1)))) OR (((t1.a1:1 > (t2.a1:7 + 5)) OR (t1.a1:1 <= (t2.a2:8 + 5))) AND ((t1.a2:2 > (t2.a2:8 + 7)) OR (t1.a1:1 <= (t2.a2:8 - 9)))) [outer=(1,2,7,8), immutable, constraints=(/1: (/NULL - ])] # Can't consume both OR terms with a join to a single Scan relation. Both sides -# of each equijoin predicate must be applied on a simple Scan or Select. +# of each interesting predicate must be applied on a simple Scan or Select. opt expect-not=SplitDisjunctionOfJoinTerms SELECT * FROM a t2 INNER JOIN a t1 ON TRUE LEFT OUTER JOIN a t3 ON (t1.a1 = t3.a1 OR t2.a2 = t3.a2) ---- diff --git a/pkg/sql/opt/xform/testdata/rules/join b/pkg/sql/opt/xform/testdata/rules/join index c6e0c2d3b77c..38ff5169ce6d 100644 --- a/pkg/sql/opt/xform/testdata/rules/join +++ b/pkg/sql/opt/xform/testdata/rules/join @@ -7362,13 +7362,13 @@ project ├── immutable └── inner-join (lookup nyc_neighborhoods [as=n]) ├── columns: c.boroname:9 c.geom:10!null name:16 n.geom:17!null - ├── key columns: [21] = [14] + ├── key columns: [61] = [14] ├── lookup columns are key ├── immutable ├── inner-join (inverted nyc_neighborhoods@nyc_neighborhoods_geo_idx [as=n]) - │ ├── columns: c.boroname:9 c.geom:10 n.gid:21!null + │ ├── columns: c.boroname:9 c.geom:10 n.gid:61!null │ ├── inverted-expr - │ │ └── st_coveredby(c.geom:10, n.geom:24) AND (st_dwithin(c.geom:10, n.geom:24, 50.0) OR st_intersects('0102000000020000000000000000000000000000000000000000000000000000000000000000000040', n.geom:24)) + │ │ └── st_coveredby(c.geom:10, n.geom:64) AND (st_dwithin(c.geom:10, n.geom:64, 50.0) OR st_intersects('0102000000020000000000000000000000000000000000000000000000000000000000000000000040', n.geom:64)) │ ├── scan nyc_census_blocks [as=c] │ │ └── columns: c.boroname:9 c.geom:10 │ └── filters (true) @@ -7511,12 +7511,12 @@ project # It's not possible to generate an inverted join when there is an OR with a # non-geospatial function. -opt expect-not=GenerateInvertedJoins +opt expect-not=GenerateInvertedJoins disable=SplitDisjunctionOfJoinTerms SELECT n.name, c.boroname FROM nyc_census_blocks AS c JOIN nyc_neighborhoods@nyc_neighborhoods_geo_idx AS n -ON ST_Covers(c.geom, n.geom) OR n.name LIKE 'Upper%' +ON ST_Covers(c.geom, n.geom) OR n.name LIKE c.boroname || 'Upper%' ---- project ├── columns: name:16 boroname:9 @@ -7530,7 +7530,7 @@ project │ ├── columns: name:16 n.geom:17 │ └── flags: force-index=nyc_neighborhoods_geo_idx └── filters - └── st_covers(c.geom:10, n.geom:17) OR (name:16 LIKE 'Upper%') [outer=(10,16,17), immutable] + └── st_covers(c.geom:10, n.geom:17) OR (name:16 LIKE (c.boroname:9 || 'Upper%')) [outer=(9,10,16,17), immutable] # Semi-joins are supported by converting them to a paired-join consisting of # an inner inverted join followed by a left semi lookup join. @@ -9792,66 +9792,66 @@ project │ ├── right columns: a:25 b:26 c:27 │ ├── cardinality: [0 - 2] │ ├── ordering: +1 - │ ├── project - │ │ ├── columns: a:13!null b:14 c:15 + │ ├── semi-join (lookup pqr@q) + │ │ ├── columns: a:13!null b:14 c:15!null + │ │ ├── key columns: [14 105] = [19 18] + │ │ ├── lookup columns are key │ │ ├── cardinality: [0 - 1] - │ │ ├── key: (13) - │ │ ├── fd: (13)-->(14,15), (15)~~>(13,14) - │ │ ├── ordering: +13 [actual: ] - │ │ └── project - │ │ ├── columns: a:13!null b:14!null c:15!null q:19!null r:20!null - │ │ ├── cardinality: [0 - 1] - │ │ ├── key: () - │ │ ├── fd: ()-->(13-15,19,20), (15)==(20), (20)==(15), (14)==(19), (19)==(14) - │ │ └── inner-join (lookup zz) - │ │ ├── columns: a:13!null b:14!null c:15!null p:18!null q:19!null r:20!null - │ │ ├── key columns: [13] = [13] - │ │ ├── lookup columns are key - │ │ ├── cardinality: [0 - 1] - │ │ ├── key: () - │ │ ├── fd: ()-->(13-15,18-20), (19)==(14), (15)==(20), (20)==(15), (14)==(19) - │ │ ├── inner-join (lookup zz@idx_c) - │ │ │ ├── columns: a:13!null c:15!null p:18!null q:19 r:20!null - │ │ │ ├── key columns: [20] = [15] - │ │ │ ├── lookup columns are key - │ │ │ ├── cardinality: [0 - 1] - │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(13,15,18-20), (20)==(15), (15)==(20) - │ │ │ ├── scan pqr - │ │ │ │ ├── columns: p:18!null q:19 r:20 - │ │ │ │ ├── constraint: /18: [/0 - /0] - │ │ │ │ ├── cardinality: [0 - 1] - │ │ │ │ ├── key: () - │ │ │ │ └── fd: ()-->(18-20) - │ │ │ └── filters (true) - │ │ └── filters - │ │ └── q:19 = b:14 [outer=(14,19), constraints=(/14: (/NULL - ]; /19: (/NULL - ]), fd=(14)==(19), (19)==(14)] - │ └── semi-join (lookup pqr@q) - │ ├── columns: a:25!null b:26 c:27!null - │ ├── key columns: [26 121] = [31 30] - │ ├── lookup columns are key + │ │ ├── key: () + │ │ ├── fd: ()-->(13-15) + │ │ ├── project + │ │ │ ├── columns: "lookup_join_const_col_@18":105!null a:13!null b:14 c:15!null + │ │ │ ├── cardinality: [0 - 1] + │ │ │ ├── key: () + │ │ │ ├── fd: ()-->(13-15,105) + │ │ │ ├── index-join zz + │ │ │ │ ├── columns: a:13!null b:14 c:15!null + │ │ │ │ ├── cardinality: [0 - 1] + │ │ │ │ ├── key: () + │ │ │ │ ├── fd: ()-->(13-15) + │ │ │ │ └── scan zz@idx_c + │ │ │ │ ├── columns: a:13!null c:15!null + │ │ │ │ ├── constraint: /15: [/0 - /0] + │ │ │ │ ├── cardinality: [0 - 1] + │ │ │ │ ├── key: () + │ │ │ │ └── fd: ()-->(13,15) + │ │ │ └── projections + │ │ │ └── 0 [as="lookup_join_const_col_@18":105] + │ │ └── filters (true) + │ └── project + │ ├── columns: a:25!null b:26 c:27 │ ├── cardinality: [0 - 1] - │ ├── key: () - │ ├── fd: ()-->(25-27) - │ ├── project - │ │ ├── columns: "lookup_join_const_col_@30":121!null a:25!null b:26 c:27!null - │ │ ├── cardinality: [0 - 1] - │ │ ├── key: () - │ │ ├── fd: ()-->(25-27,121) - │ │ ├── index-join zz - │ │ │ ├── columns: a:25!null b:26 c:27!null - │ │ │ ├── cardinality: [0 - 1] - │ │ │ ├── key: () - │ │ │ ├── fd: ()-->(25-27) - │ │ │ └── scan zz@idx_c - │ │ │ ├── columns: a:25!null c:27!null - │ │ │ ├── constraint: /27: [/0 - /0] - │ │ │ ├── cardinality: [0 - 1] - │ │ │ ├── key: () - │ │ │ └── fd: ()-->(25,27) - │ │ └── projections - │ │ └── 0 [as="lookup_join_const_col_@30":121] - │ └── filters (true) + │ ├── key: (25) + │ ├── fd: (25)-->(26,27), (27)~~>(25,26) + │ ├── ordering: +25 [actual: ] + │ └── project + │ ├── columns: a:25!null b:26!null c:27!null q:31!null r:32!null + │ ├── cardinality: [0 - 1] + │ ├── key: () + │ ├── fd: ()-->(25-27,31,32), (27)==(32), (32)==(27), (26)==(31), (31)==(26) + │ └── inner-join (lookup zz) + │ ├── columns: a:25!null b:26!null c:27!null p:30!null q:31!null r:32!null + │ ├── key columns: [25] = [25] + │ ├── lookup columns are key + │ ├── cardinality: [0 - 1] + │ ├── key: () + │ ├── fd: ()-->(25-27,30-32), (31)==(26), (27)==(32), (32)==(27), (26)==(31) + │ ├── inner-join (lookup zz@idx_c) + │ │ ├── columns: a:25!null c:27!null p:30!null q:31 r:32!null + │ │ ├── key columns: [32] = [27] + │ │ ├── lookup columns are key + │ │ ├── cardinality: [0 - 1] + │ │ ├── key: () + │ │ ├── fd: ()-->(25,27,30-32), (32)==(27), (27)==(32) + │ │ ├── scan pqr + │ │ │ ├── columns: p:30!null q:31 r:32 + │ │ │ ├── constraint: /30: [/0 - /0] + │ │ │ ├── cardinality: [0 - 1] + │ │ │ ├── key: () + │ │ │ └── fd: ()-->(30-32) + │ │ └── filters (true) + │ └── filters + │ └── q:31 = b:26 [outer=(26,31), constraints=(/26: (/NULL - ]; /31: (/NULL - ]), fd=(26)==(31), (31)==(26)] └── aggregations ├── const-agg [as=b:2, outer=(2)] │ └── b:2 diff --git a/pkg/sql/sessiondatapb/local_only_session_data.proto b/pkg/sql/sessiondatapb/local_only_session_data.proto index da95e99f7714..7176f3fb89bb 100644 --- a/pkg/sql/sessiondatapb/local_only_session_data.proto +++ b/pkg/sql/sessiondatapb/local_only_session_data.proto @@ -329,6 +329,12 @@ message LocalOnlySessionData { // DeclareCursorStatementTimeoutEnabled controls whether statement timeouts // apply during DECLARE CURSOR. bool declare_cursor_statement_timeout_enabled = 90; + // OptimizerUseImprovedSplitDisjunctionForJoins enables the optimizer to split + // disjunctions (OR expressions) in more cases in join conditions by building a + // UNION of two join expressions. If this setting is true, all disjunctions in + // inner, semi, and anti joins will be split. If false, only disjunctions + // potentially containing an equijoin condition will be split. + bool optimizer_use_improved_split_disjunction_for_joins = 91; /////////////////////////////////////////////////////////////////////////// // WARNING: consider whether a session parameter you're adding needs to // diff --git a/pkg/sql/vars.go b/pkg/sql/vars.go index 98c1ba844fdb..99a9b4f00c52 100644 --- a/pkg/sql/vars.go +++ b/pkg/sql/vars.go @@ -2463,6 +2463,23 @@ var varGen = map[string]sessionVar{ }, GlobalDefault: globalTrue, }, + + // CockroachDB extension. + `optimizer_use_improved_split_disjunction_for_joins`: { + GetStringVal: makePostgresBoolGetStringValFn(`optimizer_use_improved_split_disjunction_for_joins`), + Set: func(_ context.Context, m sessionDataMutator, s string) error { + b, err := paramparse.ParseBoolVar("optimizer_use_improved_split_disjunction_for_joins", s) + if err != nil { + return err + } + m.SetOptimizerUseImprovedSplitDisjunctionForJoins(b) + return nil + }, + Get: func(evalCtx *extendedEvalContext, _ *kv.Txn) (string, error) { + return formatBoolAsPostgresSetting(evalCtx.SessionData().OptimizerUseImprovedSplitDisjunctionForJoins), nil + }, + GlobalDefault: globalTrue, + }, } // We want test coverage for this on and off so make it metamorphic.