Skip to content

Commit 47279b9

Browse files
authored
planner: add tolerance for row count floating point comparison (#59241) (#59278)
close #59133
1 parent b6f2b6e commit 47279b9

File tree

4 files changed

+16
-7
lines changed

4 files changed

+16
-7
lines changed

pkg/planner/core/cost/factors_thresholds.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ const (
2424
SelectionFactor = 0.8
2525

2626
DistinctFactor = 0.8
27+
28+
// ToleranceFactor is an arbitrary value used in (some) floating point
29+
// comparisons to account for precision errors
30+
ToleranceFactor = 0.00001
2731
)
2832

2933
// AggFuncFactor is the basic factor for aggregation.

pkg/planner/core/find_best_task.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1680,7 +1680,8 @@ func convertToIndexMergeScan(ds *logicalop.DataSource, prop *property.PhysicalPr
16801680
scans = append(scans, scan)
16811681
}
16821682
totalRowCount := path.CountAfterAccess
1683-
if prop.ExpectedCnt < ds.StatsInfo().RowCount {
1683+
// Add an arbitrary tolerance factor to account for comparison with floating point
1684+
if (prop.ExpectedCnt + cost.ToleranceFactor) < ds.StatsInfo().RowCount {
16841685
totalRowCount *= prop.ExpectedCnt / ds.StatsInfo().RowCount
16851686
}
16861687
ts, remainingFilters2, moreColumn, err := buildIndexMergeTableScan(ds, path.TableFilters, totalRowCount, candidate.isMatchProp)
@@ -2925,7 +2926,8 @@ func getOriginalPhysicalTableScan(ds *logicalop.DataSource, prop *property.Physi
29252926
}.Init(ds.SCtx(), ds.QueryBlockOffset())
29262927
ts.SetSchema(ds.Schema().Clone())
29272928
rowCount := path.CountAfterAccess
2928-
if prop.ExpectedCnt < ds.StatsInfo().RowCount {
2929+
// Add an arbitrary tolerance factor to account for comparison with floating point
2930+
if (prop.ExpectedCnt + cost.ToleranceFactor) < ds.StatsInfo().RowCount {
29292931
rowCount = cardinality.AdjustRowCountForTableScanByLimit(ds.SCtx(),
29302932
ds.StatsInfo(), ds.TableStats, ds.StatisticTable,
29312933
path, prop.ExpectedCnt, isMatchProp && prop.SortItems[0].Desc)

pkg/planner/core/stats.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,8 @@ func deriveIndexPathStats(ds *logicalop.DataSource, path *util.AccessPath, _ []e
234234
path.IndexFilters = append(path.IndexFilters, indexFilters...)
235235
// If the `CountAfterAccess` is less than `stats.RowCount`, there must be some inconsistent stats info.
236236
// We prefer the `stats.RowCount` because it could use more stats info to calculate the selectivity.
237-
if path.CountAfterAccess < ds.StatsInfo().RowCount && !isIm {
237+
// Add an arbitrary tolerance factor to account for comparison with floating point
238+
if (path.CountAfterAccess+cost.ToleranceFactor) < ds.StatsInfo().RowCount && !isIm {
238239
path.CountAfterAccess = math.Min(ds.StatsInfo().RowCount/cost.SelectionFactor, float64(ds.StatisticTable.RealtimeCount))
239240
}
240241
if path.IndexFilters != nil {
@@ -333,7 +334,8 @@ func deriveTablePathStats(ds *logicalop.DataSource, path *util.AccessPath, conds
333334
path.CountAfterAccess, err = cardinality.GetRowCountByIntColumnRanges(ds.SCtx(), &ds.StatisticTable.HistColl, pkCol.ID, path.Ranges)
334335
// If the `CountAfterAccess` is less than `stats.RowCount`, there must be some inconsistent stats info.
335336
// We prefer the `stats.RowCount` because it could use more stats info to calculate the selectivity.
336-
if path.CountAfterAccess < ds.StatsInfo().RowCount && !isIm {
337+
// Add an arbitrary tolerance factor to account for comparison with floating point
338+
if (path.CountAfterAccess+cost.ToleranceFactor) < ds.StatsInfo().RowCount && !isIm {
337339
path.CountAfterAccess = math.Min(ds.StatsInfo().RowCount/cost.SelectionFactor, float64(ds.StatisticTable.RealtimeCount))
338340
}
339341
return err
@@ -371,7 +373,8 @@ func deriveCommonHandleTablePathStats(ds *logicalop.DataSource, path *util.Acces
371373
}
372374
// If the `CountAfterAccess` is less than `stats.RowCount`, there must be some inconsistent stats info.
373375
// We prefer the `stats.RowCount` because it could use more stats info to calculate the selectivity.
374-
if path.CountAfterAccess < ds.StatsInfo().RowCount && !isIm {
376+
// Add an arbitrary tolerance factor to account for comparison with floating point
377+
if (path.CountAfterAccess+cost.ToleranceFactor) < ds.StatsInfo().RowCount && !isIm {
375378
path.CountAfterAccess = math.Min(ds.StatsInfo().RowCount/cost.SelectionFactor, float64(ds.StatisticTable.RealtimeCount))
376379
}
377380
return nil

tests/integrationtest/r/clustered_index.result

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,11 @@ id estRows task access object operator info
109109
StreamAgg_17 1.00 root funcs:count(Column#8)->Column#6
110110
└─IndexReader_18 1.00 root index:StreamAgg_9
111111
└─StreamAgg_9 1.00 cop[tikv] funcs:count(1)->Column#8
112-
└─IndexRangeScan_16 133.89 cop[tikv] table:tbl_0, index:idx_3(col_0) range:[803163,+inf], keep order:false
112+
└─IndexRangeScan_16 107.12 cop[tikv] table:tbl_0, index:idx_3(col_0) range:[803163,+inf], keep order:false
113113
explain select count(*) from wout_cluster_index.tbl_0 where col_0 >= 803163 ;
114114
id estRows task access object operator info
115115
StreamAgg_17 1.00 root funcs:count(Column#9)->Column#7
116116
└─IndexReader_18 1.00 root index:StreamAgg_9
117117
└─StreamAgg_9 1.00 cop[tikv] funcs:count(1)->Column#9
118-
└─IndexRangeScan_16 133.89 cop[tikv] table:tbl_0, index:idx_3(col_0) range:[803163,+inf], keep order:false
118+
└─IndexRangeScan_16 107.12 cop[tikv] table:tbl_0, index:idx_3(col_0) range:[803163,+inf], keep order:false
119119
set @@tidb_enable_outer_join_reorder=false;

0 commit comments

Comments
 (0)