@@ -892,13 +892,13 @@ func buildIndexJoinInner2TableScan(
892
892
return nil
893
893
}
894
894
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 )
896
896
// The index merge join's inner plan is different from index join, so we
897
897
// should construct another inner plan for it.
898
898
// Because we can't keep order for union scan, if there is a union scan in inner task,
899
899
// we can't construct index merge join.
900
900
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 )
902
902
}
903
903
ranges = indexJoinResult .chosenRanges
904
904
} else {
@@ -932,13 +932,13 @@ func buildIndexJoinInner2TableScan(
932
932
}
933
933
buffer .WriteString ("]" )
934
934
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 )
936
936
// The index merge join's inner plan is different from index join, so we
937
937
// should construct another inner plan for it.
938
938
// Because we can't keep order for union scan, if there is a union scan in inner task,
939
939
// we can't construct index merge join.
940
940
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 )
942
942
}
943
943
}
944
944
var (
@@ -1000,7 +1000,7 @@ func buildIndexJoinInner2IndexScan(
1000
1000
maxOneRow = ok && (sf .FuncName .L == ast .EQ )
1001
1001
}
1002
1002
}
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 )
1004
1004
failpoint .Inject ("MockOnlyEnableIndexHashJoin" , func (val failpoint.Value ) {
1005
1005
if val .(bool ) && ! p .SCtx ().GetSessionVars ().InRestrictedSQL && innerTask != nil {
1006
1006
failpoint .Return (constructIndexHashJoin (p , prop , outerIdx , innerTask , indexJoinResult .chosenRanges , keyOff2IdxOff , indexJoinResult .chosenPath , indexJoinResult .lastColManager ))
@@ -1017,7 +1017,7 @@ func buildIndexJoinInner2IndexScan(
1017
1017
// Because we can't keep order for union scan, if there is a union scan in inner task,
1018
1018
// we can't construct index merge join.
1019
1019
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 )
1021
1021
if innerTask2 != nil {
1022
1022
joins = append (joins , constructIndexMergeJoin (p , prop , outerIdx , innerTask2 , indexJoinResult .chosenRanges , keyOff2IdxOff , indexJoinResult .chosenPath , indexJoinResult .lastColManager )... )
1023
1023
}
@@ -1031,13 +1031,27 @@ func constructInnerTableScanTask(
1031
1031
prop * property.PhysicalProperty ,
1032
1032
wrapper * indexJoinInnerChildWrapper ,
1033
1033
ranges ranger.Ranges ,
1034
- _ []* expression.Column ,
1035
1034
rangeInfo string ,
1036
1035
keepOrder bool ,
1037
1036
desc bool ,
1038
1037
rowCount float64 ,
1039
1038
) 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 {
1041
1055
// If `ds.TableInfo.GetPartitionInfo() != nil`,
1042
1056
// it means the data source is a partition table reader.
1043
1057
// If the inner task need to keep order, the partition table reader can't satisfy it.
@@ -1082,7 +1096,7 @@ func constructInnerTableScanTask(
1082
1096
StatsVersion : ds .StatsInfo ().StatsVersion ,
1083
1097
// NDV would not be used in cost computation of IndexJoin, set leave it as default nil.
1084
1098
})
1085
- usedStats := p .SCtx ().GetSessionVars ().StmtCtx .GetUsedStatsInfo (false )
1099
+ usedStats := ds .SCtx ().GetSessionVars ().StmtCtx .GetUsedStatsInfo (false )
1086
1100
if usedStats != nil && usedStats .GetUsedInfo (ts .physicalTableID ) != nil {
1087
1101
ts .usedStatsInfo = usedStats .GetUsedInfo (ts .physicalTableID )
1088
1102
}
@@ -1101,7 +1115,7 @@ func constructInnerTableScanTask(
1101
1115
ts .PlanPartInfo = copTask .physPlanPartInfo
1102
1116
selStats := ts .StatsInfo ().Scale (selectivity )
1103
1117
ts .addPushedDownSelection (copTask , selStats )
1104
- return constructIndexJoinInnerSideTaskWithAggCheck ( p , prop , copTask , ds , nil , wrapper )
1118
+ return copTask
1105
1119
}
1106
1120
1107
1121
func constructIndexJoinInnerSideTask (curTask base.Task , prop * property.PhysicalProperty , zippedChildren []base.LogicalPlan , skipAgg bool ) base.Task {
@@ -1227,15 +1241,33 @@ func constructInnerIndexScanTask(
1227
1241
path * util.AccessPath ,
1228
1242
ranges ranger.Ranges ,
1229
1243
filterConds []expression.Expression ,
1230
- _ []* expression.Column ,
1231
1244
idxOffset2joinKeyOffset []int ,
1232
1245
rangeInfo string ,
1233
1246
keepOrder bool ,
1234
1247
desc bool ,
1235
1248
rowCount float64 ,
1236
1249
maxOneRow bool ,
1237
1250
) 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 {
1239
1271
// If `ds.TableInfo.GetPartitionInfo() != nil`,
1240
1272
// it means the data source is a partition table reader.
1241
1273
// If the inner task need to keep order, the partition table reader can't satisfy it.
@@ -1299,7 +1331,7 @@ func constructInnerIndexScanTask(
1299
1331
// change before calling `(*copTask).finishIndexPlan`, we don't know the stats information of `ts` currently and on
1300
1332
// the other hand, it may be hard to identify `StatsVersion` of `ts` in `(*copTask).finishIndexPlan`.
1301
1333
ts .SetStats (& property.StatsInfo {StatsVersion : ds .TableStats .StatsVersion })
1302
- usedStats := p .SCtx ().GetSessionVars ().StmtCtx .GetUsedStatsInfo (false )
1334
+ usedStats := ds .SCtx ().GetSessionVars ().StmtCtx .GetUsedStatsInfo (false )
1303
1335
if usedStats != nil && usedStats .GetUsedInfo (ts .physicalTableID ) != nil {
1304
1336
ts .usedStatsInfo = usedStats .GetUsedInfo (ts .physicalTableID )
1305
1337
}
@@ -1405,7 +1437,7 @@ func constructInnerIndexScanTask(
1405
1437
logutil .BgLogger ().Warn ("unexpected error happened during addPushedDownSelection function" , zap .Error (err ))
1406
1438
return nil
1407
1439
}
1408
- return constructIndexJoinInnerSideTaskWithAggCheck ( p , prop , cop , ds , path , wrapper )
1440
+ return cop
1409
1441
}
1410
1442
1411
1443
// construct the inner join task by inner child plan tree
@@ -1599,6 +1631,7 @@ func tryToGetIndexJoin(p *logicalop.LogicalJoin, prop *property.PhysicalProperty
1599
1631
return candidates , canForced
1600
1632
}
1601
1633
candidates = handleFilterIndexJoinHints (p , candidates )
1634
+ // todo: if any variables banned it, why bother to generate it first?
1602
1635
return filterIndexJoinBySessionVars (p .SCtx (), candidates ), false
1603
1636
}
1604
1637
0 commit comments