From df908bf31f2532810737fb8f22fdb6fa32237ee9 Mon Sep 17 00:00:00 2001 From: Chengpeng Yan <41809508+Reminiscent@users.noreply.github.com> Date: Mon, 2 Aug 2021 16:57:06 +0800 Subject: [PATCH] planner: add binding info for explain stmt (#26403) --- bindinfo/bind_test.go | 18 ++++++++++++++++++ planner/optimize.go | 12 +++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/bindinfo/bind_test.go b/bindinfo/bind_test.go index 6e0b341d76..256c1be1ec 100644 --- a/bindinfo/bind_test.go +++ b/bindinfo/bind_test.go @@ -1891,6 +1891,24 @@ func (s *testSuite) TestReCreateBind(c *C) { c.Assert(rows[0][3], Equals, "using") } +func (s *testSuite) TestExplainShowBindSQL(c *C) { + tk := testkit.NewTestKit(c, s.store) + s.cleanBindingEnv(tk) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int, b int, key(a))") + + tk.MustExec("create global binding for select * from t using select * from t use index(a)") + tk.MustQuery("select original_sql, bind_sql from mysql.bind_info where default_db != 'mysql'").Check(testkit.Rows( + "select * from `test` . `t` SELECT * FROM `test`.`t` USE INDEX (`a`)", + )) + + tk.MustExec("explain select * from t") + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 Using the bindSQL: SELECT * FROM `test`.`t` USE INDEX (`a`)")) + tk.MustExec("explain analyze select * from t") + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 Using the bindSQL: SELECT * FROM `test`.`t` USE INDEX (`a`)")) +} + func (s *testSuite) TestDMLIndexHintBind(c *C) { tk := testkit.NewTestKit(c, s.store) s.cleanBindingEnv(tk) diff --git a/planner/optimize.go b/planner/optimize.go index 8fbd1d3782..64afe1b329 100644 --- a/planner/optimize.go +++ b/planner/optimize.go @@ -170,11 +170,17 @@ func Optimize(ctx context.Context, sctx sessionctx.Context, node ast.Node, is in if binding != nil && binding.Status == bindinfo.Using { if sctx.GetSessionVars().UsePlanBaselines { stmtHints, warns = handleStmtHints(binding.Hint.GetFirstTableHints()) + if _, ok := stmtNode.(*ast.ExplainStmt); ok { + sctx.GetSessionVars().StmtCtx.AppendWarning(errors.Errorf("Using the bindSQL: %v", binding.BindSQL)) + } } return bestPlan, names, nil } bestCostAmongHints := math.MaxFloat64 - var bestPlanAmongHints plannercore.Plan + var ( + bestPlanAmongHints plannercore.Plan + bestPlanBindSQL string + ) originHints := hint.CollectHint(stmtNode) // Try to find the best binding. for _, binding := range bindRecord.Bindings { @@ -201,8 +207,12 @@ func Optimize(ctx context.Context, sctx sessionctx.Context, node ast.Node, is in } bestCostAmongHints = cost bestPlanAmongHints = plan + bestPlanBindSQL = binding.BindSQL } } + if _, ok := stmtNode.(*ast.ExplainStmt); ok && bestPlanBindSQL != "" { + sctx.GetSessionVars().StmtCtx.AppendWarning(errors.Errorf("Using the bindSQL: %v", bestPlanBindSQL)) + } // 1. If it is a select query. // 2. If there is already a evolution task, we do not need to handle it again. // 3. If the origin binding contain `read_from_storage` hint, we should ignore the evolve task.