planner: allow to use dynamic mode to access partitioning tables without global-stats (#44264)

close pingcap/tidb#44262
This commit is contained in:
Yuanjia Zhang
2023-05-30 14:46:41 +08:00
committed by GitHub
parent 77fb135809
commit ff996e7068
3 changed files with 52 additions and 1 deletions

View File

@ -3513,3 +3513,32 @@ func TestFixControl(t *testing.T) {
require.Equal(t, output[i].Variable, rows)
}
}
func TestFixControl44262(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec(`use test`)
tk.MustExec(`set tidb_partition_prune_mode='dynamic'`)
tk.MustExec(`create table t1 (a int, b int)`)
tk.MustExec(`create table t2_part (a int, b int, key(a)) partition by hash(a) partitions 4`)
testJoin := func(q, join string) {
found := false
for _, x := range tk.MustQuery(`explain ` + q).Rows() {
if strings.Contains(x[0].(string), join) {
found = true
}
}
if !found {
t.Fatal(q, join)
}
}
testJoin(`select /*+ TIDB_INLJ(t2_part@sel_2) */ * from t1 where t1.b<10 and not exists (select 1 from t2_part where t1.a=t2_part.a and t2_part.b<20)`, "HashJoin")
tk.MustQuery(`show warnings`).Sort().Check(testkit.Rows(
`Warning 1105 disable dynamic pruning due to t2_part has no global stats`,
`Warning 1815 Optimizer Hint /*+ INL_JOIN(t2_part) */ or /*+ TIDB_INLJ(t2_part) */ is inapplicable`))
tk.MustExec(`set @@tidb_opt_fix_control = "44262:ON"`)
testJoin(`select /*+ TIDB_INLJ(t2_part@sel_2) */ * from t1 where t1.b<10 and not exists (select 1 from t2_part where t1.a=t2_part.a and t2_part.b<20)`, "IndexJoin")
tk.MustQuery(`show warnings`).Sort().Check(testkit.Rows()) // no warning
}

View File

@ -4584,8 +4584,14 @@ func (b *PlanBuilder) buildDataSource(ctx context.Context, tn *ast.TableName, as
tblStats := h.GetTableStats(tableInfo)
isDynamicEnabled := b.ctx.GetSessionVars().IsDynamicPartitionPruneEnabled()
globalStatsReady := tblStats.IsInitialized()
allowDynamicWithoutStats := false
fixValue, ok := b.ctx.GetSessionVars().GetOptimizerFixControlValue(variable.TiDBOptFixControl44262)
if ok && variable.TiDBOptOn(fixValue) {
allowDynamicWithoutStats = true
}
// If dynamic partition prune isn't enabled or global stats is not ready, we won't enable dynamic prune mode in query
usePartitionProcessor := !isDynamicEnabled || !globalStatsReady
usePartitionProcessor := !isDynamicEnabled || (!globalStatsReady && !allowDynamicWithoutStats)
failpoint.Inject("forceDynamicPrune", func(val failpoint.Value) {
if val.(bool) {

View File

@ -1485,6 +1485,22 @@ type SessionVars struct {
HypoIndexes map[string]map[string]map[string]*model.IndexInfo // dbName -> tblName -> idxName -> idxInfo
}
var (
// variables below are for the optimizer fix control.
// TiDBOptFixControl44262 controls whether to allow to use dynamic-mode to access partitioning tables without global-stats (#44262).
TiDBOptFixControl44262 uint64 = 44262
)
// GetOptimizerFixControlValue returns the specified value of the optimizer fix control.
func (s *SessionVars) GetOptimizerFixControlValue(key uint64) (value string, exist bool) {
if s.OptimizerFixControl == nil {
return "", false
}
value, exist = s.OptimizerFixControl[key]
return
}
// planReplayerSessionFinishedTaskKeyLen is used to control the max size for the finished plan replayer task key in session
// in order to control the used memory
const planReplayerSessionFinishedTaskKeyLen = 128