Skip to content

Commit 70999a6

Browse files
authored
planner: make index join's code about build tableScan and indexScan more clean. (#60107)
ref #60106
1 parent daa3e33 commit 70999a6

File tree

1 file changed

+47
-14
lines changed

1 file changed

+47
-14
lines changed

pkg/planner/core/exhaust_physical_plans.go

Lines changed: 47 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -892,13 +892,13 @@ func buildIndexJoinInner2TableScan(
892892
return nil
893893
}
894894
rangeInfo := indexJoinPathRangeInfo(p.SCtx(), outerJoinKeys, indexJoinResult)
895-
innerTask = constructInnerTableScanTask(p, prop, wrapper, indexJoinResult.chosenRanges.Range(), outerJoinKeys, rangeInfo, false, false, avgInnerRowCnt)
895+
innerTask = constructInnerTableScanTask(p, prop, wrapper, indexJoinResult.chosenRanges.Range(), rangeInfo, false, false, avgInnerRowCnt)
896896
// The index merge join's inner plan is different from index join, so we
897897
// should construct another inner plan for it.
898898
// Because we can't keep order for union scan, if there is a union scan in inner task,
899899
// we can't construct index merge join.
900900
if !wrapper.hasDitryWrite {
901-
innerTask2 = constructInnerTableScanTask(p, prop, wrapper, indexJoinResult.chosenRanges.Range(), outerJoinKeys, rangeInfo, true, !prop.IsSortItemEmpty() && prop.SortItems[0].Desc, avgInnerRowCnt)
901+
innerTask2 = constructInnerTableScanTask(p, prop, wrapper, indexJoinResult.chosenRanges.Range(), rangeInfo, true, !prop.IsSortItemEmpty() && prop.SortItems[0].Desc, avgInnerRowCnt)
902902
}
903903
ranges = indexJoinResult.chosenRanges
904904
} else {
@@ -932,13 +932,13 @@ func buildIndexJoinInner2TableScan(
932932
}
933933
buffer.WriteString("]")
934934
rangeInfo := buffer.String()
935-
innerTask = constructInnerTableScanTask(p, prop, wrapper, ranges, outerJoinKeys, rangeInfo, false, false, avgInnerRowCnt)
935+
innerTask = constructInnerTableScanTask(p, prop, wrapper, ranges, rangeInfo, false, false, avgInnerRowCnt)
936936
// The index merge join's inner plan is different from index join, so we
937937
// should construct another inner plan for it.
938938
// Because we can't keep order for union scan, if there is a union scan in inner task,
939939
// we can't construct index merge join.
940940
if !wrapper.hasDitryWrite {
941-
innerTask2 = constructInnerTableScanTask(p, prop, wrapper, ranges, outerJoinKeys, rangeInfo, true, !prop.IsSortItemEmpty() && prop.SortItems[0].Desc, avgInnerRowCnt)
941+
innerTask2 = constructInnerTableScanTask(p, prop, wrapper, ranges, rangeInfo, true, !prop.IsSortItemEmpty() && prop.SortItems[0].Desc, avgInnerRowCnt)
942942
}
943943
}
944944
var (
@@ -1000,7 +1000,7 @@ func buildIndexJoinInner2IndexScan(
10001000
maxOneRow = ok && (sf.FuncName.L == ast.EQ)
10011001
}
10021002
}
1003-
innerTask := constructInnerIndexScanTask(p, prop, wrapper, indexJoinResult.chosenPath, indexJoinResult.chosenRanges.Range(), indexJoinResult.chosenRemained, innerJoinKeys, indexJoinResult.idxOff2KeyOff, rangeInfo, false, false, avgInnerRowCnt, maxOneRow)
1003+
innerTask := constructInnerIndexScanTask(p, prop, wrapper, indexJoinResult.chosenPath, indexJoinResult.chosenRanges.Range(), indexJoinResult.chosenRemained, indexJoinResult.idxOff2KeyOff, rangeInfo, false, false, avgInnerRowCnt, maxOneRow)
10041004
failpoint.Inject("MockOnlyEnableIndexHashJoin", func(val failpoint.Value) {
10051005
if val.(bool) && !p.SCtx().GetSessionVars().InRestrictedSQL && innerTask != nil {
10061006
failpoint.Return(constructIndexHashJoin(p, prop, outerIdx, innerTask, indexJoinResult.chosenRanges, keyOff2IdxOff, indexJoinResult.chosenPath, indexJoinResult.lastColManager))
@@ -1017,7 +1017,7 @@ func buildIndexJoinInner2IndexScan(
10171017
// Because we can't keep order for union scan, if there is a union scan in inner task,
10181018
// we can't construct index merge join.
10191019
if !wrapper.hasDitryWrite {
1020-
innerTask2 := constructInnerIndexScanTask(p, prop, wrapper, indexJoinResult.chosenPath, indexJoinResult.chosenRanges.Range(), indexJoinResult.chosenRemained, innerJoinKeys, indexJoinResult.idxOff2KeyOff, rangeInfo, true, !prop.IsSortItemEmpty() && prop.SortItems[0].Desc, avgInnerRowCnt, maxOneRow)
1020+
innerTask2 := constructInnerIndexScanTask(p, prop, wrapper, indexJoinResult.chosenPath, indexJoinResult.chosenRanges.Range(), indexJoinResult.chosenRemained, indexJoinResult.idxOff2KeyOff, rangeInfo, true, !prop.IsSortItemEmpty() && prop.SortItems[0].Desc, avgInnerRowCnt, maxOneRow)
10211021
if innerTask2 != nil {
10221022
joins = append(joins, constructIndexMergeJoin(p, prop, outerIdx, innerTask2, indexJoinResult.chosenRanges, keyOff2IdxOff, indexJoinResult.chosenPath, indexJoinResult.lastColManager)...)
10231023
}
@@ -1031,13 +1031,27 @@ func constructInnerTableScanTask(
10311031
prop *property.PhysicalProperty,
10321032
wrapper *indexJoinInnerChildWrapper,
10331033
ranges ranger.Ranges,
1034-
_ []*expression.Column,
10351034
rangeInfo string,
10361035
keepOrder bool,
10371036
desc bool,
10381037
rowCount float64,
10391038
) base.Task {
1040-
ds := wrapper.ds
1039+
copTask := constructDS2TableScanTask(wrapper.ds, ranges, rangeInfo, keepOrder, desc, rowCount)
1040+
if copTask == nil {
1041+
return nil
1042+
}
1043+
return constructIndexJoinInnerSideTaskWithAggCheck(p, prop, copTask.(*CopTask), wrapper.ds, nil, wrapper)
1044+
}
1045+
1046+
// constructInnerTableScanTask is specially used to construct the inner plan for PhysicalIndexJoin.
1047+
func constructDS2TableScanTask(
1048+
ds *logicalop.DataSource,
1049+
ranges ranger.Ranges,
1050+
rangeInfo string,
1051+
keepOrder bool,
1052+
desc bool,
1053+
rowCount float64,
1054+
) base.Task {
10411055
// If `ds.TableInfo.GetPartitionInfo() != nil`,
10421056
// it means the data source is a partition table reader.
10431057
// If the inner task need to keep order, the partition table reader can't satisfy it.
@@ -1082,7 +1096,7 @@ func constructInnerTableScanTask(
10821096
StatsVersion: ds.StatsInfo().StatsVersion,
10831097
// NDV would not be used in cost computation of IndexJoin, set leave it as default nil.
10841098
})
1085-
usedStats := p.SCtx().GetSessionVars().StmtCtx.GetUsedStatsInfo(false)
1099+
usedStats := ds.SCtx().GetSessionVars().StmtCtx.GetUsedStatsInfo(false)
10861100
if usedStats != nil && usedStats.GetUsedInfo(ts.physicalTableID) != nil {
10871101
ts.usedStatsInfo = usedStats.GetUsedInfo(ts.physicalTableID)
10881102
}
@@ -1101,7 +1115,7 @@ func constructInnerTableScanTask(
11011115
ts.PlanPartInfo = copTask.physPlanPartInfo
11021116
selStats := ts.StatsInfo().Scale(selectivity)
11031117
ts.addPushedDownSelection(copTask, selStats)
1104-
return constructIndexJoinInnerSideTaskWithAggCheck(p, prop, copTask, ds, nil, wrapper)
1118+
return copTask
11051119
}
11061120

11071121
func constructIndexJoinInnerSideTask(curTask base.Task, prop *property.PhysicalProperty, zippedChildren []base.LogicalPlan, skipAgg bool) base.Task {
@@ -1227,15 +1241,33 @@ func constructInnerIndexScanTask(
12271241
path *util.AccessPath,
12281242
ranges ranger.Ranges,
12291243
filterConds []expression.Expression,
1230-
_ []*expression.Column,
12311244
idxOffset2joinKeyOffset []int,
12321245
rangeInfo string,
12331246
keepOrder bool,
12341247
desc bool,
12351248
rowCount float64,
12361249
maxOneRow bool,
12371250
) base.Task {
1238-
ds := wrapper.ds
1251+
copTask := constructDS2IndexScanTask(wrapper.ds, path, ranges, filterConds, idxOffset2joinKeyOffset, rangeInfo, keepOrder, desc, rowCount, maxOneRow)
1252+
if copTask == nil {
1253+
return nil
1254+
}
1255+
return constructIndexJoinInnerSideTaskWithAggCheck(p, prop, copTask.(*CopTask), wrapper.ds, path, wrapper)
1256+
}
1257+
1258+
// constructDS2IndexScanTask is specially used to construct the inner plan for PhysicalIndexJoin.
1259+
func constructDS2IndexScanTask(
1260+
ds *logicalop.DataSource,
1261+
path *util.AccessPath,
1262+
ranges ranger.Ranges,
1263+
filterConds []expression.Expression,
1264+
idxOffset2joinKeyOffset []int,
1265+
rangeInfo string,
1266+
keepOrder bool,
1267+
desc bool,
1268+
rowCount float64,
1269+
maxOneRow bool,
1270+
) base.Task {
12391271
// If `ds.TableInfo.GetPartitionInfo() != nil`,
12401272
// it means the data source is a partition table reader.
12411273
// If the inner task need to keep order, the partition table reader can't satisfy it.
@@ -1299,7 +1331,7 @@ func constructInnerIndexScanTask(
12991331
// change before calling `(*copTask).finishIndexPlan`, we don't know the stats information of `ts` currently and on
13001332
// the other hand, it may be hard to identify `StatsVersion` of `ts` in `(*copTask).finishIndexPlan`.
13011333
ts.SetStats(&property.StatsInfo{StatsVersion: ds.TableStats.StatsVersion})
1302-
usedStats := p.SCtx().GetSessionVars().StmtCtx.GetUsedStatsInfo(false)
1334+
usedStats := ds.SCtx().GetSessionVars().StmtCtx.GetUsedStatsInfo(false)
13031335
if usedStats != nil && usedStats.GetUsedInfo(ts.physicalTableID) != nil {
13041336
ts.usedStatsInfo = usedStats.GetUsedInfo(ts.physicalTableID)
13051337
}
@@ -1405,7 +1437,7 @@ func constructInnerIndexScanTask(
14051437
logutil.BgLogger().Warn("unexpected error happened during addPushedDownSelection function", zap.Error(err))
14061438
return nil
14071439
}
1408-
return constructIndexJoinInnerSideTaskWithAggCheck(p, prop, cop, ds, path, wrapper)
1440+
return cop
14091441
}
14101442

14111443
// construct the inner join task by inner child plan tree
@@ -1599,6 +1631,7 @@ func tryToGetIndexJoin(p *logicalop.LogicalJoin, prop *property.PhysicalProperty
15991631
return candidates, canForced
16001632
}
16011633
candidates = handleFilterIndexJoinHints(p, candidates)
1634+
// todo: if any variables banned it, why bother to generate it first?
16021635
return filterIndexJoinBySessionVars(p.SCtx(), candidates), false
16031636
}
16041637

0 commit comments

Comments
 (0)