From ac11792d7810c75c92429bb4f1eb74f4d12cb1d6 Mon Sep 17 00:00:00 2001 From: Kenan Yao Date: Mon, 8 Mar 2021 17:24:25 +0800 Subject: [PATCH] cherry pick #23132 to release-4.0 --- planner/core/integration_test.go | 48 +++++++++++++++---- planner/core/stats.go | 11 ++--- .../core/testdata/integration_suite_out.json | 11 +++-- 3 files changed, 49 insertions(+), 21 deletions(-) diff --git a/planner/core/integration_test.go b/planner/core/integration_test.go index 5779082c2a551..a15d007dde541 100644 --- a/planner/core/integration_test.go +++ b/planner/core/integration_test.go @@ -1145,10 +1145,10 @@ func (s *testIntegrationSerialSuite) TestIssue16837(c *C) { tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int,b int,c int,d int,e int,unique key idx_ab(a,b),unique key(c),unique key(d))") tk.MustQuery("explain select /*+ use_index_merge(t,c,idx_ab) */ * from t where a = 1 or (e = 1 and c = 1)").Check(testkit.Rows( - "IndexMerge_9 0.01 root ", + "IndexMerge_9 8.80 root ", "├─IndexRangeScan_5(Build) 10.00 cop[tikv] table:t, index:idx_ab(a, b) range:[1,1], keep order:false, stats:pseudo", "├─IndexRangeScan_6(Build) 1.00 cop[tikv] table:t, index:c(c) range:[1,1], keep order:false, stats:pseudo", - "└─Selection_8(Probe) 0.01 cop[tikv] eq(test.t.e, 1)", + "└─Selection_8(Probe) 8.80 cop[tikv] or(eq(test.t.a, 1), and(eq(test.t.e, 1), eq(test.t.c, 1)))", " └─TableRowIDScan_7 11.00 cop[tikv] table:t keep order:false, stats:pseudo")) tk.MustQuery("show warnings").Check(testkit.Rows()) tk.MustExec("insert into t values (2, 1, 1, 1, 2)") @@ -1186,10 +1186,13 @@ func (s *testIntegrationSerialSuite) TestIndexMerge(c *C) { tk.MustQuery("show warnings").Check(testkit.Rows()) tk.MustQuery("desc select /*+ use_index_merge(t) */ * from t where (a=1 and length(b)=1) or (b=1 and length(a)=1)").Check(testkit.Rows( - "TableReader_7 8000.00 root data:Selection_6", - "└─Selection_6 8000.00 cop[tikv] or(and(eq(test.t.a, 1), eq(length(cast(test.t.b)), 1)), and(eq(test.t.b, 1), eq(length(cast(test.t.a)), 1)))", - " └─TableFullScan_5 10000.00 cop[tikv] table:t keep order:false, stats:pseudo")) - tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 IndexMerge is inapplicable or disabled")) + "IndexMerge_9 1.60 root ", + "├─IndexRangeScan_5(Build) 1.00 cop[tikv] table:t, index:a(a) range:[1,1], keep order:false, stats:pseudo", + "├─IndexRangeScan_6(Build) 1.00 cop[tikv] table:t, index:b(b) range:[1,1], keep order:false, stats:pseudo", + "└─Selection_8(Probe) 1.60 cop[tikv] or(and(eq(test.t.a, 1), eq(length(cast(test.t.b)), 1)), and(eq(test.t.b, 1), eq(length(cast(test.t.a)), 1)))", + " └─TableRowIDScan_7 2.00 cop[tikv] table:t keep order:false, stats:pseudo", + )) + tk.MustQuery("show warnings").Check(testkit.Rows()) } func (s *testIntegrationSerialSuite) TestIssue16407(c *C) { @@ -1198,10 +1201,10 @@ func (s *testIntegrationSerialSuite) TestIssue16407(c *C) { tk.MustExec("drop table if exists t") tk.MustExec("create table t(a int,b char(100),key(a),key(b(10)))") tk.MustQuery("explain select /*+ use_index_merge(t) */ * from t where a=10 or b='x'").Check(testkit.Rows( - "IndexMerge_9 0.02 root ", + "IndexMerge_9 16.00 root ", "├─IndexRangeScan_5(Build) 10.00 cop[tikv] table:t, index:a(a) range:[10,10], keep order:false, stats:pseudo", "├─IndexRangeScan_6(Build) 10.00 cop[tikv] table:t, index:b(b) range:[\"x\",\"x\"], keep order:false, stats:pseudo", - "└─Selection_8(Probe) 0.02 cop[tikv] eq(test.t.b, \"x\")", + "└─Selection_8(Probe) 16.00 cop[tikv] or(eq(test.t.a, 10), eq(test.t.b, \"x\"))", " └─TableRowIDScan_7 20.00 cop[tikv] table:t keep order:false, stats:pseudo")) tk.MustQuery("show warnings").Check(testkit.Rows()) tk.MustExec("insert into t values (1, 'xx')") @@ -1832,3 +1835,32 @@ func (s *testIntegrationSuite) TestIssue22071(c *C) { tk.MustQuery("select n in (1,2) from (select a in (1,2) as n from t) g;").Sort().Check(testkit.Rows("0", "1", "1")) tk.MustQuery("select n in (1,n) from (select a in (1,2) as n from t) g;").Check(testkit.Rows("1", "1", "1")) } + +func (s *testIntegrationSuite) TestIndexMergeTableFilter(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t(a int, b int, c int, d int, key(a), key(b));") + tk.MustExec("insert into t values(10,1,1,10)") + + tk.MustQuery("explain select /*+ use_index_merge(t) */ * from t where a=10 or (b=10 and c=10)").Check(testkit.Rows( + "IndexMerge_9 16.00 root ", + "├─IndexRangeScan_5(Build) 10.00 cop[tikv] table:t, index:a(a) range:[10,10], keep order:false, stats:pseudo", + "├─IndexRangeScan_6(Build) 10.00 cop[tikv] table:t, index:b(b) range:[10,10], keep order:false, stats:pseudo", + "└─Selection_8(Probe) 16.00 cop[tikv] or(eq(test.t.a, 10), and(eq(test.t.b, 10), eq(test.t.c, 10)))", + " └─TableRowIDScan_7 20.00 cop[tikv] table:t keep order:false, stats:pseudo", + )) + tk.MustQuery("select /*+ use_index_merge(t) */ * from t where a=10 or (b=10 and c=10)").Check(testkit.Rows( + "10 1 1 10", + )) + tk.MustQuery("explain select /*+ use_index_merge(t) */ * from t where (a=10 and d=10) or (b=10 and c=10)").Check(testkit.Rows( + "IndexMerge_9 16.00 root ", + "├─IndexRangeScan_5(Build) 10.00 cop[tikv] table:t, index:a(a) range:[10,10], keep order:false, stats:pseudo", + "├─IndexRangeScan_6(Build) 10.00 cop[tikv] table:t, index:b(b) range:[10,10], keep order:false, stats:pseudo", + "└─Selection_8(Probe) 16.00 cop[tikv] or(and(eq(test.t.a, 10), eq(test.t.d, 10)), and(eq(test.t.b, 10), eq(test.t.c, 10)))", + " └─TableRowIDScan_7 20.00 cop[tikv] table:t keep order:false, stats:pseudo", + )) + tk.MustQuery("select /*+ use_index_merge(t) */ * from t where (a=10 and d=10) or (b=10 and c=10)").Check(testkit.Rows( + "10 1 1 10", + )) +} diff --git a/planner/core/stats.go b/planner/core/stats.go index a062fcf50b844..6a03e53b6ca97 100644 --- a/planner/core/stats.go +++ b/planner/core/stats.go @@ -464,16 +464,11 @@ func (ds *DataSource) buildIndexMergeOrPath(partialPaths []*util.AccessPath, cur indexMergePath := &util.AccessPath{PartialIndexPaths: partialPaths} indexMergePath.TableFilters = append(indexMergePath.TableFilters, ds.pushedDownConds[:current]...) indexMergePath.TableFilters = append(indexMergePath.TableFilters, ds.pushedDownConds[current+1:]...) - tableFilterCnt := 0 for _, path := range partialPaths { - // IndexMerge should not be used when the SQL is like 'select x from t WHERE (key1=1 AND key2=2) OR (key1=4 AND key3=6);'. - // Check issue https://github.com/pingcap/tidb/issues/22105 for details. + // If any partial path contains table filters, we need to keep the whole DNF filter in the Selection. if len(path.TableFilters) > 0 { - tableFilterCnt++ - if tableFilterCnt > 1 { - return nil - } - indexMergePath.TableFilters = append(indexMergePath.TableFilters, path.TableFilters...) + indexMergePath.TableFilters = append(indexMergePath.TableFilters, ds.pushedDownConds[current]) + break } } return indexMergePath diff --git a/planner/core/testdata/integration_suite_out.json b/planner/core/testdata/integration_suite_out.json index fa38b1dc73407..6ebc5adc2e922 100644 --- a/planner/core/testdata/integration_suite_out.json +++ b/planner/core/testdata/integration_suite_out.json @@ -897,11 +897,12 @@ { "SQL": "explain SELECT /*+ use_index_merge(t1)*/ COUNT(*) FROM t1 WHERE (key4=42 AND key6 IS NOT NULL) OR (key1=4 AND key3=6)", "Plan": [ - "StreamAgg_20 1.00 root funcs:count(Column#12)->Column#10", - "└─TableReader_21 1.00 root data:StreamAgg_9", - " └─StreamAgg_9 1.00 cop[tikv] funcs:count(1)->Column#12", - " └─Selection_19 8000.00 cop[tikv] or(and(eq(test.t1.key4, 42), not(isnull(test.t1.key6))), and(eq(test.t1.key1, 4), eq(test.t1.key3, 6)))", - " └─TableFullScan_18 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + "HashAgg_8 1.00 root funcs:count(1)->Column#10", + "└─IndexMerge_15 16.00 root ", + " ├─IndexRangeScan_11(Build) 10.00 cop[tikv] table:t1, index:i4(key4) range:[42,42], keep order:false, stats:pseudo", + " ├─IndexRangeScan_12(Build) 10.00 cop[tikv] table:t1, index:i1(key1) range:[4,4], keep order:false, stats:pseudo", + " └─Selection_14(Probe) 16.00 cop[tikv] or(and(eq(test.t1.key4, 42), not(isnull(test.t1.key6))), and(eq(test.t1.key1, 4), eq(test.t1.key3, 6)))", + " └─TableRowIDScan_13 20.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ] } ]