diff --git a/pkg/planner/core/casetest/index/index_test.go b/pkg/planner/core/casetest/index/index_test.go index e1445b64a8ffc..8e50923a16824 100644 --- a/pkg/planner/core/casetest/index/index_test.go +++ b/pkg/planner/core/casetest/index/index_test.go @@ -78,3 +78,20 @@ func TestNullConditionForPrefixIndex(t *testing.T) { " └─StreamAgg_9 1.00 cop[tikv] funcs:count(1)->Column#7", " └─IndexRangeScan_16 99.90 cop[tikv] table:t1, index:idx2(c1, c2) range:[\"0xfff\" -inf,\"0xfff\" +inf], keep order:false, stats:pseudo")) } + +func TestInvisibleIndex(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("CREATE TABLE t1 ( a INT, KEY( a ) INVISIBLE );") + tk.MustExec("INSERT INTO t1 VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);") + tk.MustQuery(`EXPLAIN SELECT a FROM t1;`).Check( + testkit.Rows( + `TableReader_5 10000.00 root data:TableFullScan_4`, + `└─TableFullScan_4 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo`)) + tk.MustExec("set session tidb_opt_use_invisible_indexes=on;") + tk.MustQuery(`EXPLAIN SELECT a FROM t1;`).Check( + testkit.Rows( + `IndexReader_7 10000.00 root index:IndexFullScan_6`, + `└─IndexFullScan_6 10000.00 cop[tikv] table:t1, index:a(a) keep order:false, stats:pseudo`)) +} diff --git a/pkg/planner/core/point_get_plan.go b/pkg/planner/core/point_get_plan.go index 00062b8165f3d..5a3aeb5bb8f9a 100644 --- a/pkg/planner/core/point_get_plan.go +++ b/pkg/planner/core/point_get_plan.go @@ -740,7 +740,7 @@ func newBatchPointGetPlan( } } for _, idxInfo := range tbl.Indices { - if !idxInfo.Unique || idxInfo.State != model.StatePublic || idxInfo.Invisible || idxInfo.MVIndex || + if !idxInfo.Unique || idxInfo.State != model.StatePublic || (idxInfo.Invisible && !ctx.GetSessionVars().OptimizerUseInvisibleIndexes) || idxInfo.MVIndex || !indexIsAvailableByHints(idxInfo, indexHints) { continue } @@ -1135,7 +1135,7 @@ func checkTblIndexForPointPlan(ctx sessionctx.Context, tblName *ast.TableName, s dbName = ctx.GetSessionVars().CurrentDB } for _, idxInfo := range tbl.Indices { - if !idxInfo.Unique || idxInfo.State != model.StatePublic || idxInfo.Invisible || idxInfo.MVIndex || + if !idxInfo.Unique || idxInfo.State != model.StatePublic || (idxInfo.Invisible && !ctx.GetSessionVars().OptimizerUseInvisibleIndexes) || idxInfo.MVIndex || !indexIsAvailableByHints(idxInfo, tblName.IndexHints) { continue } diff --git a/pkg/session/session.go b/pkg/session/session.go index 65b473e21a4a5..c0f2a62933e1c 100644 --- a/pkg/session/session.go +++ b/pkg/session/session.go @@ -1957,9 +1957,7 @@ func (s *session) getInternalSession(execOption sqlexec.ExecOption) (*session, f if cache := s.sessionVars.InspectionTableCache; cache != nil { se.sessionVars.InspectionTableCache = cache } - if ok := s.sessionVars.OptimizerUseInvisibleIndexes; ok { - se.sessionVars.OptimizerUseInvisibleIndexes = true - } + se.sessionVars.OptimizerUseInvisibleIndexes = s.sessionVars.OptimizerUseInvisibleIndexes if execOption.SnapshotTS != 0 { if err := se.sessionVars.SetSystemVar(variable.TiDBSnapshot, strconv.FormatUint(execOption.SnapshotTS, 10)); err != nil { diff --git a/pkg/sessionctx/variable/sysvar.go b/pkg/sessionctx/variable/sysvar.go index fd9b055f66c28..3cf5a661af81d 100644 --- a/pkg/sessionctx/variable/sysvar.go +++ b/pkg/sessionctx/variable/sysvar.go @@ -2396,6 +2396,10 @@ var defaultSysVars = []*SysVar{ s.EnableAdvancedJoinHint = TiDBOptOn(val) return nil }}, + {Scope: ScopeSession, Name: TiDBOptUseInvisibleIndexes, Value: BoolToOnOff(false), Type: TypeBool, SetSession: func(s *SessionVars, val string) error { + s.OptimizerUseInvisibleIndexes = TiDBOptOn(val) + return nil + }}, {Scope: ScopeGlobal | ScopeSession, Name: TiDBAnalyzePartitionConcurrency, Value: strconv.FormatInt(DefTiDBAnalyzePartitionConcurrency, 10), MinValue: 1, MaxValue: uint64(config.GetGlobalConfig().Performance.AnalyzePartitionConcurrencyQuota), SetSession: func(s *SessionVars, val string) error { s.AnalyzePartitionConcurrency = int(TidbOptInt64(val, DefTiDBAnalyzePartitionConcurrency)) diff --git a/pkg/sessionctx/variable/tidb_vars.go b/pkg/sessionctx/variable/tidb_vars.go index 670c1c16ca0ed..64e2db2faea2b 100644 --- a/pkg/sessionctx/variable/tidb_vars.go +++ b/pkg/sessionctx/variable/tidb_vars.go @@ -851,7 +851,8 @@ const ( // TiDBOptAdvancedJoinHint indicates whether the join method hint is compatible with join order hint. TiDBOptAdvancedJoinHint = "tidb_opt_advanced_join_hint" - + // TiDBOptUseInvisibleIndexes indicates whether to use invisible indexes. + TiDBOptUseInvisibleIndexes = "tidb_opt_use_invisible_indexes" // TiDBAnalyzePartitionConcurrency indicates concurrency for save/read partitions stats in Analyze TiDBAnalyzePartitionConcurrency = "tidb_analyze_partition_concurrency" // TiDBMergePartitionStatsConcurrency indicates the concurrency when merge partition stats into global stats diff --git a/pkg/util/admin/admin.go b/pkg/util/admin/admin.go index 8ca6b30d380ad..c674da59f182b 100644 --- a/pkg/util/admin/admin.go +++ b/pkg/util/admin/admin.go @@ -70,9 +70,10 @@ const ( // otherwise it returns an error and the corresponding index's offset. func CheckIndicesCount(ctx sessionctx.Context, dbName, tableName string, indices []string) (byte, int, error) { // Here we need check all indexes, includes invisible index + originOptUseInvisibleIdx := ctx.GetSessionVars().OptimizerUseInvisibleIndexes ctx.GetSessionVars().OptimizerUseInvisibleIndexes = true defer func() { - ctx.GetSessionVars().OptimizerUseInvisibleIndexes = false + ctx.GetSessionVars().OptimizerUseInvisibleIndexes = originOptUseInvisibleIdx }() var snapshot uint64