Repository: pingcap/tidb
File: pkg/executor/importer/import.go (Go)

Code before:
				return &fileMeta, nil
			}); err != nil {
			return err
		}
		// filter unmatch files
		for _, f := range processedFiles {
			if f != nil {
				dataFiles = append(dataFiles, f)
				totalSize += f.FileSize
				totalRealSize += f.RealSize
			}
		}
	}
	if e.InImportInto && isAutoDetectingFormat && e.Format != DataFormatCSV {
		if err2 = e.checkNonCSVFormatOptions(); err2 != nil {
			return err2
		}
	}

	e.dataFiles = dataFiles
	e.totalRealSize = totalRealSize
	e.TotalFileSize = totalSize

	return nil
}

// CalResourceParams calculates resource related parameters according to the total
// file size and target node cpu count.
func (e *LoadDataController) CalResourceParams(ctx context.Context, ksCodec []byte) error {
	start := time.Now()
	targetNodeCPUCnt, err := handle.GetCPUCountOfNode(ctx)
	if err != nil {
		return err
	}
	factors, err := handle.GetScheduleTuneFactors(ctx, e.Keyspace)
	if err != nil {
		return err
	}
	totalSize := e.totalRealSize
	failpoint.InjectCall("mockImportDataSize", &totalSize)
	numOfIndexGenKV := GetNumOfIndexGenKV(e.TableInfo)
	var indexSizeRatio float64
	if numOfIndexGenKV > 0 {
		indexSizeRatio, err = e.sampleIndexSizeRatio(ctx, ksCodec)
		if err != nil {
			e.logger.Warn("meet error when sampling index size ratio", zap.Error(err))
		}
	}
	cal := scheduler.NewRCCalc(totalSize, targetNodeCPUCnt, indexSizeRatio, factors)
	e.ThreadCnt = cal.CalcRequiredSlots()
	e.MaxNodeCnt = cal.CalcMaxNodeCountForImportInto()

Review comment (suggestion):
`totalRealSize` is only accumulated in the wildcard branch. In the single-file branch (`idx == -1`), `totalRealSize` remains 0, but you still assign `e.totalRealSize = totalRealSize`, which makes `CalResourceParams` treat the import size as 0 for single-file imports (and can miscalculate thread/max-node). Please set `totalRealSize` for the single-file path (e.g., from `fileMeta.RealSize`) before assigning it to `e.totalRealSize`.
```suggestion

	// For single-file imports, totalRealSize might not have been accumulated;
	// derive it from the only data file to avoid treating the size as zero.
	if totalRealSize == 0 && len(dataFiles) == 1 {
		totalRealSize = dataFiles[0].RealSize
	}
```

Code after:
			}); err != nil {
			return err
		}
		// filter unmatch files
		for _, f := range processedFiles {
			if f != nil {
				dataFiles = append(dataFiles, f)
			}
		}
	}
	if e.InImportInto && isAutoDetectingFormat && e.Format != DataFormatCSV {
		if err2 = e.checkNonCSVFormatOptions(); err2 != nil {
			return err2
		}
	}
	var totalSize, totalRealSize int64
	for _, dfile := range dataFiles {
		totalSize += dfile.FileSize
		realSize := dfile.RealSize
		failpoint.Inject("amplifyRealSize", func(val failpoint.Value) {
			factor := int64(val.(int))
			realSize *= factor
		})
		totalRealSize += realSize
	}

	e.dataFiles = dataFiles
	e.TotalFileSize = totalSize
	e.TotalRealSize = totalRealSize

	return nil
}

// CalResourceParams calculates resource related parameters according to the total
// file size and target node cpu count.
func (e *LoadDataController) CalResourceParams(ctx context.Context, ksCodec []byte) error {
	start := time.Now()
	targetNodeCPUCnt, err := handle.GetCPUCountOfNode(ctx)
	if err != nil {
		return err
	}
	factors, err := handle.GetScheduleTuneFactors(ctx, e.Keyspace)
	if err != nil {
		return err
	}
	totalSize := e.TotalRealSize
	numOfIndexGenKV := GetNumOfIndexGenKV(e.TableInfo)
	var indexSizeRatio float64
	if numOfIndexGenKV > 0 {
		indexSizeRatio, err = e.sampleIndexSizeRatio(ctx, ksCodec)
		if err != nil {