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: fix tiflash path will be identified as table dual #49338

Merged
merged 2 commits into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions pkg/planner/core/casetest/enforcempp/enforce_mpp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ func TestEnforceMPP(t *testing.T) {
tk.MustExec("create table t(a int, b int)")
tk.MustExec("create index idx on t(a)")
tk.MustExec("CREATE TABLE `s` (\n `a` int(11) DEFAULT NULL,\n `b` int(11) DEFAULT NULL,\n `c` int(11) DEFAULT NULL,\n `d` int(11) DEFAULT NULL,\n UNIQUE KEY `a` (`a`),\n KEY `ii` (`a`,`b`)\n)")
tk.MustExec("create table t3(id int, sala char(10), name char(100), primary key(id, sala)) partition by list columns (sala)(partition p1 values in('a'));")

// Default RPC encoding may cause statistics explain result differ and then the test unstable.
tk.MustExec("set @@tidb_enable_chunk_rpc = on")
Expand All @@ -65,6 +66,12 @@ func TestEnforceMPP(t *testing.T) {
Available: true,
}
}
if tblInfo.Name.L == "t3" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}

var input []string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
"explain format='verbose' select count(*) from t where a=1",
"explain format='verbose' select /*+ read_from_storage(tikv[t]) */ count(*) from t where a=1",
"explain format='verbose' select /*+ read_from_storage(tiflash[t]) */ count(*) from t where a=1",
"explain select /*+ READ_FROM_STORAGE(TIFLASH[s]) */ a from s where a = 10 and b is null; -- index path huristic rule will prune tiflash path"
"explain select /*+ READ_FROM_STORAGE(TIFLASH[s]) */ a from s where a = 10 and b is null; -- index path huristic rule will prune tiflash path",
"explain select /*+ read_from_storage(tiflash[t3]) */ * from t3 where sala='a' and id =1; -- once hinted, walk with tiflash range scan",
"explain select * from t3 where sala='a' and id =1; -- once not hinted, walk with tikv point get"
]
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,13 +177,33 @@
{
"SQL": "explain select /*+ READ_FROM_STORAGE(TIFLASH[s]) */ a from s where a = 10 and b is null; -- index path huristic rule will prune tiflash path",
"Plan": [
"TableReader_12 0.10 root MppVersion: 2, data:ExchangeSender_11",
"└─ExchangeSender_11 0.10 mpp[tiflash] ExchangeType: PassThrough",
"TableReader_9 0.10 root MppVersion: 2, data:ExchangeSender_8",
"└─ExchangeSender_8 0.10 mpp[tiflash] ExchangeType: PassThrough",
" └─Projection_5 0.10 mpp[tiflash] test.s.a",
" └─Selection_10 0.10 mpp[tiflash] isnull(test.s.b)",
" └─TableFullScan_9 10.00 mpp[tiflash] table:s pushed down filter:eq(test.s.a, 10), keep order:false, stats:pseudo"
" └─Selection_7 0.10 mpp[tiflash] isnull(test.s.b)",
" └─TableFullScan_6 10.00 mpp[tiflash] table:s pushed down filter:eq(test.s.a, 10), keep order:false, stats:pseudo"
],
"Warn": null
},
{
"SQL": "explain select /*+ read_from_storage(tiflash[t3]) */ * from t3 where sala='a' and id =1; -- once hinted, walk with tiflash range scan",
"Plan": [
"TableReader_12 0.01 root MppVersion: 2, data:ExchangeSender_11",
"└─ExchangeSender_11 0.01 mpp[tiflash] ExchangeType: PassThrough",
" └─TableRangeScan_10 1.00 mpp[tiflash] table:t3, partition:p1 range:[1 \"a\",1 \"a\"], keep order:false, stats:pseudo"
],
"Warn": [
"disable dynamic pruning due to t3 has no global stats"
]
},
{
"SQL": "explain select * from t3 where sala='a' and id =1; -- once not hinted, walk with tikv point get",
"Plan": [
"Point_Get_6 1.00 root table:t3, partition:p1, clustered index:PRIMARY(id, sala) "
],
"Warn": [
"disable dynamic pruning due to t3 has no global stats"
]
}
]
},
Expand Down
26 changes: 23 additions & 3 deletions pkg/planner/core/stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,22 @@ func (ds *DataSource) derivePathStatsAndTryHeuristics() error {
selected, uniqueBest, refinedBest *util.AccessPath
isRefinedPath bool
)
// step1: if user prefer tiFlash store type, tiFlash path should always be built anyway ahead.
var tiflashPath *util.AccessPath
if ds.preferStoreType&preferTiFlash != 0 {
for _, path := range ds.possibleAccessPaths {
if path.StoreType == kv.TiFlash {
err := ds.deriveTablePathStats(path, ds.pushedDownConds, false)
if err != nil {
return err
}
path.IsSingleScan = true
tiflashPath = path
break
}
}
}
// step2: kv path should follow the heuristic rules.
for _, path := range ds.possibleAccessPaths {
if path.IsTablePath() {
err := ds.deriveTablePathStats(path, ds.pushedDownConds, false)
Expand All @@ -318,7 +334,9 @@ func (ds *DataSource) derivePathStatsAndTryHeuristics() error {
ds.deriveIndexPathStats(path, ds.pushedDownConds, false)
path.IsSingleScan = ds.isSingleScan(path.FullIdxCols, path.FullIdxColLens)
}
// step: 3
// Try some heuristic rules to select access path.
// tiFlash path also have table-range-scan (range point like here) to be heuristic treated.
if len(path.Ranges) == 0 {
selected = path
break
Expand Down Expand Up @@ -381,13 +399,15 @@ func (ds *DataSource) derivePathStatsAndTryHeuristics() error {
// heuristic rule pruning other path should consider hint prefer.
// If no hints and some path matches a heuristic rule, just remove other possible paths.
if selected != nil {
// if user wanna tiFlash read, while current heuristic choose a TiKV path. so we shouldn't prune other paths.
ds.possibleAccessPaths[0] = selected
ds.possibleAccessPaths = ds.possibleAccessPaths[:1]
// if user wanna tiFlash read, while current heuristic choose a TiKV path. so we shouldn't prune tiFlash path.
keep := ds.preferStoreType&preferTiFlash != 0 && selected.StoreType != kv.TiFlash
if keep {
// also keep tiflash path as well.
ds.possibleAccessPaths = append(ds.possibleAccessPaths, tiflashPath)
return nil
}
ds.possibleAccessPaths[0] = selected
ds.possibleAccessPaths = ds.possibleAccessPaths[:1]
var tableName string
if ds.TableAsName.O == "" {
tableName = ds.tableInfo.Name.O
Expand Down