code: func (b *BucketFeedback) getBoundaries(num int) []types.Datum {
  	// Get all the possible new boundaries.
  	vals := make([]types.Datum, 0, len(b.feedback)*2+2)
  	for _, fb := range b.feedback {
  		vals = append(vals, *fb.Lower, *fb.Upper)
  	}
  	vals = append(vals, *b.lower)
  	err := types.SortDatums(nil, vals)
  	if err != nil {
  		logutil.Logger(context.Background()).Debug("sort datums failed", zap.Error(err))
  		vals = vals[:0]
  		vals = append(vals, *b.lower, *b.upper)
  		return vals
  	}
  	total, interval := 0, len(vals)/num
  	// Pick values per `interval`.
  	for i := 0; i < len(vals); i, total = i+interval, total+1 {
  		vals[total] = vals[i]
  	}
  	// Append the upper bound.
  	vals[total] = *b.upper
  	vals = vals[:total+1]
  	total = 1
  	// Erase the repeat values.
  	for i := 1; i < len(vals); i++ {
  		cmp, err := vals[total-1].CompareDatum(nil, &vals[i])
  		if err != nil {
  			logutil.Logger(context.Background()).Debug("compare datum failed", zap.Any("value1", vals[total-1]), zap.Any("value2", vals[i]), zap.Error(err))
  			continue
  		}
  		if cmp == 0 {
  			continue
  		}
  		vals[total] = vals[i]
  		total++
  	}
  	return vals[:total]
  }
docs: // getBoundaries gets the new boundaries after split.