planner: allow to use dynamic mode to access partitioning tables without global-stats (#44264)
close pingcap/tidb#44262
This commit is contained in:
@ -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
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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
|
||||
|
||||
Reference in New Issue
Block a user