Repository: pingcap/tidb
File: pkg/statistics/handle/usage/session_stats_collect.go (Go)

Code before:
	for id := range deltaMap {
		tableIDs = append(tableIDs, id)
	}
	slices.Sort(tableIDs)

	// Dump stats delta in batches.
	for i := 0; i < len(tableIDs); i += dumpDeltaBatchSize {
		end := min(i+dumpDeltaBatchSize, len(tableIDs))

		batchTableIDs := tableIDs[i:end]
		var (
			statsVersion uint64
			batchUpdates []*storage.DeltaUpdate
		)
		batchStart := time.Now()
		err := utilstats.CallWithSCtx(s.statsHandle.SPool(), func(sctx sessionctx.Context) error {
			is := sctx.GetLatestInfoSchema().(infoschema.InfoSchema)
			batchUpdates = make([]*storage.DeltaUpdate, 0, len(batchTableIDs))
			// Collect all updates in the batch.
			for _, id := range batchTableIDs {
				item := deltaMap[id]
				if !s.needDumpStatsDelta(is, dumpAll, id, &item, batchStart) {
					deltaMap[id] = item
					continue
				}
				deltaMap[id] = item
				batchUpdates = append(batchUpdates, storage.NewDeltaUpdate(id, item, false))
			}
			if time.Since(batchStart) > tooSlowThreshold {
				statslogutil.StatsSampleLogger().Warn("Collecting batch updates is too slow",
					zap.Int("tableCount", len(batchUpdates)),
					zap.Duration("duration", time.Since(batchStart)))
			}

			if len(batchUpdates) == 0 {
				return nil
			}

			// Process all updates in the batch with a single transaction.
			// Note: batchUpdates may be modified in dumpStatsDeltaToKV. (e.g. sorting, updating IsLocked)
			startTs, updated, err := s.dumpStatsDeltaToKV(is, sctx, batchUpdates)
			if err != nil {
				return errors.Trace(err)
			}
			statsVersion = startTs
			// Note: Ensure we use the updated slice after dumpStatsDeltaToKV,
			// because dumpStatsDeltaToKV may modify the underlying array of batchUpdates.
			// For example, dumpStatsDeltaToKV may sort the array.
			batchUpdates = updated
			intest.AssertFunc(
				func() bool {

Review comment (performance):
The write-back on line 149 is unnecessary when dumping stats. When `needDumpStatsDelta` returns true, the item gets added to `batchUpdates` (line 150) and later deleted from `deltaMap` (line 184), making this assignment redundant. Consider removing line 149 to avoid the unnecessary write operation for items that will be dumped.
```suggestion

```

Code after:
	}
	slices.Sort(tableIDs)

	// Dump stats delta in batches.
	for i := 0; i < len(tableIDs); i += dumpDeltaBatchSize {
		end := min(i+dumpDeltaBatchSize, len(tableIDs))

		batchTableIDs := tableIDs[i:end]
		var (
			statsVersion uint64
			batchUpdates []*storage.DeltaUpdate
		)
		batchStart := time.Now()
		err := utilstats.CallWithSCtx(s.statsHandle.SPool(), func(sctx sessionctx.Context) error {
			is := sctx.GetLatestInfoSchema().(infoschema.InfoSchema)
			batchUpdates = make([]*storage.DeltaUpdate, 0, len(batchTableIDs))
			// Collect all updates in the batch.
			for _, id := range batchTableIDs {
				// NOTE: Ensure InitTime is initialized before evaluating dump conditions.
				item := deltaMap[id]
				if item.InitTime.IsZero() {
					item.InitTime = batchStart
					deltaMap[id] = item
				}
				needDump := s.needDumpStatsDelta(is, dumpAll, id, item, batchStart)
				if !needDump {
					continue
				}
				batchUpdates = append(batchUpdates, storage.NewDeltaUpdate(id, item, false))
			}
			if time.Since(batchStart) > tooSlowThreshold {
				statslogutil.StatsSampleLogger().Warn("Collecting batch updates is too slow",
					zap.Int("tableCount", len(batchUpdates)),
					zap.Duration("duration", time.Since(batchStart)))
			}

			if len(batchUpdates) == 0 {
				return nil
			}

			// Process all updates in the batch with a single transaction.
			// Note: batchUpdates may be modified in dumpStatsDeltaToKV. (e.g. sorting, updating IsLocked)
			startTs, updated, err := s.dumpStatsDeltaToKV(is, sctx, batchUpdates)
			if err != nil {
				return errors.Trace(err)
			}
			statsVersion = startTs
			// Note: Ensure we use the updated slice after dumpStatsDeltaToKV,
			// because dumpStatsDeltaToKV may modify the underlying array of batchUpdates.
			// For example, dumpStatsDeltaToKV may sort the array.
			batchUpdates = updated