planner: generate the additional filter in table filter when enable plan cache (#28722)

This commit is contained in:
Chengpeng Yan
2021-10-12 17:01:26 +08:00
committed by GitHub
parent d5bd9f030b
commit 4c4d3f6daa
3 changed files with 63 additions and 15 deletions

View File

@ -672,17 +672,18 @@ func (s *testPrepareSerialSuite) TestIssue28259(c *C) {
tk.MustExec("drop table if exists t;")
tk.MustExec("CREATE TABLE t (a int, b int, index idx(a));")
tk.MustExec("insert into t values(1, 0);")
tk.MustExec(`prepare stmt from 'select a from t where (a between ? and ? or a < ?) and b < 1;'`)
tk.MustExec(`prepare stmt from 'select /*+ USE_INDEX(t, idx) */ a from t where (a between ? and ? or a < ?) and b < 1;'`)
tk.MustExec("set @a=0, @b=2, @c=2;")
tk.MustQuery("execute stmt using @a,@b,@c;").Check(testkit.Rows("1"))
tkProcess = tk.Se.ShowProcess()
ps = []*util.ProcessInfo{tkProcess}
tk.Se.SetSessionManager(&mockSessionManager1{PS: ps})
res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10))
c.Assert(len(res.Rows()), Equals, 6)
c.Assert(len(res.Rows()), Equals, 5)
c.Assert(res.Rows()[1][0], Matches, ".*IndexLookUp.*")
c.Assert(res.Rows()[2][0], Matches, ".*Selection.*")
c.Assert(res.Rows()[3][0], Matches, ".*IndexRangeScan.*")
c.Assert(res.Rows()[2][0], Matches, ".*IndexRangeScan.*")
c.Assert(res.Rows()[3][0], Matches, ".*Selection.*")
c.Assert(res.Rows()[4][0], Matches, ".*TableRowIDScan.*")
tk.MustExec("set @a=2, @b=1, @c=1;")
tk.MustQuery("execute stmt using @a,@b,@c;").Check(testkit.Rows())
@ -692,17 +693,18 @@ func (s *testPrepareSerialSuite) TestIssue28259(c *C) {
ps = []*util.ProcessInfo{tkProcess}
tk.Se.SetSessionManager(&mockSessionManager1{PS: ps})
res = tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10))
c.Assert(len(res.Rows()), Equals, 6)
c.Assert(len(res.Rows()), Equals, 5)
c.Assert(res.Rows()[1][0], Matches, ".*IndexLookUp.*")
c.Assert(res.Rows()[2][0], Matches, ".*Selection.*")
c.Assert(res.Rows()[3][0], Matches, ".*IndexFullScan.*")
c.Assert(res.Rows()[2][0], Matches, ".*IndexFullScan.*")
c.Assert(res.Rows()[3][0], Matches, ".*Selection.*")
c.Assert(res.Rows()[4][0], Matches, ".*TableRowIDScan.*")
res = tk.MustQuery("explain format = 'brief' select a from t use index(idx) " +
res = tk.MustQuery("explain format = 'brief' select /*+ USE_INDEX(t, idx) */ a from t use index(idx) " +
"where (a between 0 and 2 or a < 2) and b < 1;")
c.Assert(len(res.Rows()), Equals, 5)
c.Assert(res.Rows()[1][0], Matches, ".*IndexLookUp.*")
c.Assert(res.Rows()[2][0], Matches, ".*IndexRangeScan.*")
res = tk.MustQuery("explain format = 'brief' select a from t use index(idx) " +
res = tk.MustQuery("explain format = 'brief' select /*+ USE_INDEX(t, idx) */ a from t use index(idx) " +
"where (a between 2 and 1 or a < 1) and b < 1;")
c.Assert(len(res.Rows()), Equals, 5)
c.Assert(res.Rows()[1][0], Matches, ".*IndexLookUp.*")
@ -771,3 +773,46 @@ func (s *testPrepareSerialSuite) TestIssue28259(c *C) {
c.Assert(res.Rows()[1][4], Equals, "eq(test.t.d, 5), or(and(gt(test.t.a, 1), and(lt(test.t.a, 5), gt(test.t.b, 2))), and(gt(test.t.a, 8), and(lt(test.t.a, 10), gt(test.t.c, 3)))), or(and(gt(test.t.a, 1), lt(test.t.a, 5)), and(gt(test.t.a, 8), lt(test.t.a, 10)))")
c.Assert(res.Rows()[2][0], Matches, ".*TableRangeScan.*")
}
func (s *testPrepareSerialSuite) TestIssue28696(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
orgEnable := core.PreparedPlanCacheEnabled()
defer func() {
core.SetPreparedPlanCache(orgEnable)
}()
core.SetPreparedPlanCache(true)
var err error
tk.Se, err = session.CreateSession4TestWithOpt(s.store, &session.Opt{
PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64),
})
c.Assert(err, IsNil)
tk.MustExec("use test")
tk.MustExec("set @@tidb_enable_collect_execution_info=0;")
tk.MustExec("drop table if exists t1;")
tk.MustExec("create table t1(a int primary key, b varchar(255), c int);")
tk.MustExec("create unique index b on t1(b(3));")
tk.MustExec("insert into t1 values(1,'abcdfsafd',1),(2,'addfdsafd',2),(3,'ddcdsaf',3),(4,'bbcsa',4);")
tk.MustExec(`prepare stmt from "select a from t1 where b = ?";`)
tk.MustExec("set @a='bbcsa';")
tk.MustQuery("execute stmt using @a;").Check(testkit.Rows("4"))
tkProcess := tk.Se.ShowProcess()
ps := []*util.ProcessInfo{tkProcess}
tk.Se.SetSessionManager(&mockSessionManager1{PS: ps})
res := tk.MustQuery("explain for connection " + strconv.FormatUint(tkProcess.ID, 10))
c.Assert(len(res.Rows()), Equals, 5)
c.Assert(res.Rows()[1][0], Matches, ".*IndexLookUp.*")
c.Assert(res.Rows()[2][0], Matches, ".*IndexRangeScan.*")
c.Assert(res.Rows()[3][0], Matches, ".*Selection.*")
c.Assert(res.Rows()[4][0], Matches, ".*TableRowIDScan.*")
res = tk.MustQuery("explain format = 'brief' select a from t1 where b = 'bbcsa';")
c.Assert(len(res.Rows()), Equals, 5)
c.Assert(res.Rows()[1][0], Matches, ".*IndexLookUp.*")
c.Assert(res.Rows()[2][0], Matches, ".*IndexRangeScan.*")
c.Assert(res.Rows()[3][0], Matches, ".*Selection.*")
c.Assert(res.Rows()[4][0], Matches, ".*TableRowIDScan.*")
}

View File

@ -827,10 +827,6 @@ func RemoveDupExprs(ctx sessionctx.Context, exprs []Expression) []Expression {
exists := make(map[string]struct{}, len(exprs))
sc := ctx.GetSessionVars().StmtCtx
for _, expr := range exprs {
if MaybeOverOptimized4PlanCache(ctx, []Expression{expr}) {
res = append(res, expr)
continue
}
key := string(expr.HashCode(sc))
if _, ok := exists[key]; !ok || IsMutableEffectsExpr(expr) {
res = append(res, expr)

View File

@ -1347,9 +1347,16 @@ func (is *PhysicalIndexScan) initSchema(idxExprCols []*expression.Column, isDoub
func (is *PhysicalIndexScan) addPushedDownSelection(copTask *copTask, p *DataSource, path *util.AccessPath, finalStats *property.StatsInfo) {
// Add filter condition to table plan now.
indexConds, tableConds := path.IndexFilters, path.TableFilters
indexConds = keepAccessCondsAsFilter4PlanCache(is.ctx, path.AccessConds, indexConds)
tableConds, copTask.rootTaskConds = SplitSelCondsWithVirtualColumn(tableConds)
if len(tableConds) > 0 {
// If we have table conditions, we should keep the addition filter conditions
// from the path's access conditions to the table filter not the index filter.
// The reason is when the index is the prefix index, it will get the wrong results.
tableConds = keepAccessCondsAsFilter4PlanCache(is.ctx, path.AccessConds, tableConds)
} else {
indexConds = keepAccessCondsAsFilter4PlanCache(is.ctx, path.AccessConds, indexConds)
}
var newRootConds []expression.Expression
indexConds, newRootConds = expression.PushDownExprs(is.ctx.GetSessionVars().StmtCtx, indexConds, is.ctx.GetClient(), kv.TiKV)
@ -1986,8 +1993,8 @@ func (ts *PhysicalTableScan) addPushedDownSelectionToMppTask(mpp *mppTask, stats
}
func (ts *PhysicalTableScan) addPushedDownSelection(copTask *copTask, stats *property.StatsInfo) {
ts.filterCondition = keepAccessCondsAsFilter4PlanCache(ts.ctx, ts.AccessCondition, ts.filterCondition)
ts.filterCondition, copTask.rootTaskConds = SplitSelCondsWithVirtualColumn(ts.filterCondition)
ts.filterCondition = keepAccessCondsAsFilter4PlanCache(ts.ctx, ts.AccessCondition, ts.filterCondition)
var newRootConds []expression.Expression
ts.filterCondition, newRootConds = expression.PushDownExprs(ts.ctx.GetSessionVars().StmtCtx, ts.filterCondition, ts.ctx.GetClient(), ts.StoreType)
copTask.rootTaskConds = append(copTask.rootTaskConds, newRootConds...)