Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

planner, sessionctx : Add 'last_plan_from_cache' to... (#16321) #16830

Merged
merged 14 commits into from
Apr 30, 2020
2 changes: 2 additions & 0 deletions executor/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -1691,6 +1691,8 @@ func ResetContextOfStmt(ctx sessionctx.Context, s ast.StmtNode) (err error) {
vars.SysErrorCount = errCount
vars.SysWarningCount = warnCount
vars.StmtCtx = sc
vars.PrevFoundInPlanCache = vars.FoundInPlanCache
vars.FoundInPlanCache = false
return
}

Expand Down
5 changes: 5 additions & 0 deletions executor/set.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ package executor

import (
"context"
"fmt"
"strings"

"github.com/pingcap/errors"
Expand Down Expand Up @@ -174,6 +175,10 @@ func (e *SetExecutor) setSysVariable(name string, v *expression.VarAssignment) e
if name == variable.TxnIsolationOneShot && sessionVars.InTxn() {
return errors.Trace(ErrCantChangeTxCharacteristics)
}
if name == variable.TiDBFoundInPlanCache {
sessionVars.StmtCtx.AppendWarning(fmt.Errorf("Set operation for '%s' will not take effect", variable.TiDBFoundInPlanCache))
return nil
}
err = variable.SetSessionSystemVar(sessionVars, name, value)
if err != nil {
return err
Expand Down
23 changes: 22 additions & 1 deletion planner/core/common_plans.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/pingcap/tidb/privilege"
"github.com/pingcap/tidb/sessionctx"
"github.com/pingcap/tidb/sessionctx/stmtctx"
"github.com/pingcap/tidb/sessionctx/variable"
"github.com/pingcap/tidb/table"
"github.com/pingcap/tidb/types"
driver "github.com/pingcap/tidb/types/parser_driver"
Expand Down Expand Up @@ -263,6 +264,12 @@ func (e *Execute) checkPreparedPriv(ctx context.Context, sctx sessionctx.Context
return err
}

func (e *Execute) setFoundInPlanCache(sctx sessionctx.Context, opt bool) error {
vars := sctx.GetSessionVars()
err := vars.SetSystemVar(variable.TiDBFoundInPlanCache, variable.BoolToIntStr(opt))
return err
}

func (e *Execute) getPhysicalPlan(ctx context.Context, sctx sessionctx.Context, is infoschema.InfoSchema, preparedStmt *CachedPrepareStmt) error {
stmtCtx := sctx.GetSessionVars().StmtCtx
prepared := preparedStmt.PreparedAst
Expand All @@ -282,6 +289,10 @@ func (e *Execute) getPhysicalPlan(ctx context.Context, sctx sessionctx.Context,
} else {
planCacheCounter.Inc()
}
err = e.setFoundInPlanCache(sctx, true)
if err != nil {
return err
}
e.names = names
e.Plan = plan
stmtCtx.PointExec = true
Expand All @@ -307,12 +318,16 @@ func (e *Execute) getPhysicalPlan(ctx context.Context, sctx sessionctx.Context,
}
}
if planValid {
err := e.setFoundInPlanCache(sctx, true)
if err != nil {
return err
}
if metrics.ResettablePlanCacheCounterFortTest {
metrics.PlanCacheCounter.WithLabelValues("prepare").Inc()
} else {
planCacheCounter.Inc()
}
err := e.rebuildRange(cachedVal.Plan)
err = e.rebuildRange(cachedVal.Plan)
if err != nil {
return err
}
Expand All @@ -335,10 +350,16 @@ func (e *Execute) getPhysicalPlan(ctx context.Context, sctx sessionctx.Context,
e.Plan = p
_, isTableDual := p.(*PhysicalTableDual)
if !isTableDual && prepared.UseCache {
err = e.setFoundInPlanCache(sctx, true)
if err != nil {
return err
}
cached := NewPSTMTPlanCacheValue(p, names, stmtCtx.TblInfo2UnionScan)
preparedStmt.NormalizedPlan, preparedStmt.PlanDigest = NormalizePlan(p)
stmtCtx.SetPlanDigest(preparedStmt.NormalizedPlan, preparedStmt.PlanDigest)
sctx.PreparedPlanCache().Put(cacheKey, cached)
} else {
err = e.setFoundInPlanCache(sctx, false)
}
return err
}
Expand Down
40 changes: 40 additions & 0 deletions planner/core/prepare_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,46 @@ func (s *testPlanSerialSuite) TestPlanCacheUnionScan(c *C) {
c.Check(cnt, Equals, float64(6))
}

func (s *testPlanSerialSuite) TestPlanCacheHitInfo(c *C) {
defer testleak.AfterTest(c)()
store, dom, err := newStoreWithBootstrap()
c.Assert(err, IsNil)
tk := testkit.NewTestKit(c, store)
orgEnable := core.PreparedPlanCacheEnabled()
defer func() {
dom.Close()
store.Close()
core.SetPreparedPlanCache(orgEnable)
}()
core.SetPreparedPlanCache(true)

tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{
PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64),
})
c.Assert(err, IsNil)

tk.MustExec("use test")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(id int)")
tk.MustExec("insert into t values (1),(2),(3),(4)")
tk.MustExec("prepare stmt from 'select * from t where id=?'")
tk.MustExec("prepare stmt2 from 'select /*+ ignore_plan_cache() */ * from t where id=?'")
tk.MustExec("set @doma = 1")
// Test if last_plan_from_cache is appropriately initialized.
tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("0"))
tk.MustQuery("execute stmt using @doma").Check(testkit.Rows("1"))
// Test if last_plan_from_cache is updated after a plan cache hit.
tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("1"))
tk.MustQuery("execute stmt2 using @doma").Check(testkit.Rows("1"))
// Test if last_plan_from_cache is updated after a plan cache miss caused by a prepared statement.
tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("0"))
// Test if last_plan_from_cache is updated after a plan cache miss caused by a usual statement.
tk.MustQuery("execute stmt using @doma").Check(testkit.Rows("1"))
tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("1"))
tk.MustQuery("select * from t where id=1").Check(testkit.Rows("1"))
tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("0"))
}

func (s *testPrepareSuite) TestPrepareForGroupByMultiItems(c *C) {
defer testleak.AfterTest(c)()
store, dom, err := newStoreWithBootstrap()
Expand Down
9 changes: 9 additions & 0 deletions sessionctx/variable/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,11 @@ type SessionVars struct {
// WindowingUseHighPrecision determines whether to compute window operations without loss of precision.
// see https://dev.mysql.com/doc/refman/8.0/en/window-function-optimization.html for more details.
WindowingUseHighPrecision bool

// FoundInPlanCache indicates whether this statement was found in plan cache.
FoundInPlanCache bool
// PrevFoundInPlanCache indicates whether the last statement was found in plan cache.
PrevFoundInPlanCache bool
}

// PreparedParams contains the parameters of the current prepared statement when executing it.
Expand Down Expand Up @@ -679,6 +684,8 @@ func NewSessionVars() *SessionVars {
MetricSchemaRangeDuration: DefTiDBMetricSchemaRangeDuration,
SequenceState: NewSequenceState(),
WindowingUseHighPrecision: true,
PrevFoundInPlanCache: DefTiDBFoundInPlanCache,
FoundInPlanCache: DefTiDBFoundInPlanCache,
}
vars.KVVars = kv.NewVariables(&vars.Killed)
vars.Concurrency = Concurrency{
Expand Down Expand Up @@ -1247,6 +1254,8 @@ func (s *SessionVars) SetSystemVar(name string, val string) error {
atomic.StoreUint64(&config.GetGlobalConfig().Log.QueryLogMaxLen, uint64(tidbOptInt64(val, logutil.DefaultQueryLogMaxLen)))
case TiDBCheckMb4ValueInUTF8:
config.GetGlobalConfig().CheckMb4ValueInUTF8 = TiDBOptOn(val)
case TiDBFoundInPlanCache:
s.FoundInPlanCache = TiDBOptOn(val)
}
s.systems[name] = val
return nil
Expand Down
1 change: 1 addition & 0 deletions sessionctx/variable/sysvar.go
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,7 @@ var defaultSysVars = []*SysVar{
{ScopeSession, TiDBEnableSlowLog, BoolToIntStr(logutil.DefaultTiDBEnableSlowLog)},
{ScopeSession, TiDBQueryLogMaxLen, strconv.Itoa(logutil.DefaultQueryLogMaxLen)},
{ScopeSession, TiDBCheckMb4ValueInUTF8, BoolToIntStr(config.GetGlobalConfig().CheckMb4ValueInUTF8)},
{ScopeSession, TiDBFoundInPlanCache, BoolToIntStr(DefTiDBFoundInPlanCache)},
}

// SynonymsSysVariables is synonyms of system variables.
Expand Down
4 changes: 4 additions & 0 deletions sessionctx/variable/tidb_vars.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,9 @@ const (

// TiDBCheckMb4ValueInUTF8 is used to control whether to enable the check wrong utf8 value.
TiDBCheckMb4ValueInUTF8 = "tidb_check_mb4_value_in_utf8"

// TiDBFoundInPlanCache indicates whether the last statement was found in plan cache
TiDBFoundInPlanCache = "last_plan_from_cache"
)

// TiDB system variable names that both in session and global scope.
Expand Down Expand Up @@ -479,6 +482,7 @@ const (
DefTiDBStoreLimit = 0
DefTiDBMetricSchemaStep = 60 // 60s
DefTiDBMetricSchemaRangeDuration = 60 // 60s
DefTiDBFoundInPlanCache = false
)

// Process global variables.
Expand Down
5 changes: 4 additions & 1 deletion sessionctx/variable/varsutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ func GetSessionOnlySysVars(s *SessionVars, key string) (string, bool, error) {
return BoolToIntStr(config.GetGlobalConfig().CheckMb4ValueInUTF8), true, nil
case TiDBCapturePlanBaseline:
return CapturePlanBaseline.GetVal(), true, nil
case TiDBFoundInPlanCache:
return BoolToIntStr(s.PrevFoundInPlanCache), true, nil
}
sVal, ok := s.GetSystemVar(key)
if ok {
Expand Down Expand Up @@ -417,7 +419,8 @@ func ValidateSetSystemVar(vars *SessionVars, name string, value string, scope Sc
TiDBBatchDelete, TiDBBatchCommit, TiDBEnableCascadesPlanner, TiDBEnableWindowFunction, TiDBPProfSQLCPU,
TiDBLowResolutionTSO, TiDBEnableIndexMerge, TiDBEnableNoopFuncs,
TiDBCheckMb4ValueInUTF8, TiDBEnableSlowLog, TiDBRecordPlanInSlowLog,
TiDBScatterRegion, TiDBGeneralLog, TiDBConstraintCheckInPlace, TiDBEnableVectorizedExpression:
TiDBScatterRegion, TiDBGeneralLog, TiDBConstraintCheckInPlace,
TiDBEnableVectorizedExpression, TiDBFoundInPlanCache:
fallthrough
case GeneralLog, AvoidTemporalUpgrade, BigTables, CheckProxyUsers, LogBin,
CoreFile, EndMakersInJSON, SQLLogBin, OfflineMode, PseudoSlaveMode, LowPriorityUpdates,
Expand Down
8 changes: 8 additions & 0 deletions sessionctx/variable/varsutil_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ func (s *testVarsutilSuite) TestNewSessionVars(c *C) {
c.Assert(vars.AllowWriteRowID, Equals, DefOptWriteRowID)
c.Assert(vars.TiDBOptJoinReorderThreshold, Equals, DefTiDBOptJoinReorderThreshold)
c.Assert(vars.EnableFastAnalyze, Equals, DefTiDBUseFastAnalyze)
c.Assert(vars.FoundInPlanCache, Equals, DefTiDBFoundInPlanCache)

assertFieldsGreaterThanZero(c, reflect.ValueOf(vars.Concurrency))
assertFieldsGreaterThanZero(c, reflect.ValueOf(vars.MemQuota))
Expand Down Expand Up @@ -434,6 +435,13 @@ func (s *testVarsutilSuite) TestVarsutil(c *C) {
c.Assert(val, Equals, "0")
err = SetSessionSystemVar(v, TiDBStmtSummaryMaxSQLLength, types.NewStringDatum("a"))
c.Assert(err, ErrorMatches, ".*Incorrect argument type to variable 'tidb_stmt_summary_max_sql_length'")

err = SetSessionSystemVar(v, TiDBFoundInPlanCache, types.NewStringDatum("1"))
c.Assert(err, IsNil)
val, err = GetSessionSystemVar(v, TiDBFoundInPlanCache)
c.Assert(err, IsNil)
c.Assert(val, Equals, "0")
c.Assert(v.systems[TiDBFoundInPlanCache], Equals, "1")
}

func (s *testVarsutilSuite) TestSetOverflowBehave(c *C) {
Expand Down