Skip to content

Commit

Permalink
statistics: fix merge global stats panic if the partition hasn't been…
Browse files Browse the repository at this point in the history
… analyzed before (#39123)

close #39121
  • Loading branch information
Yisaer authored Nov 15, 2022
1 parent 661a6b6 commit 6af4e4b
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 6 deletions.
21 changes: 21 additions & 0 deletions executor/analyze_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -417,3 +417,24 @@ func TestAnalyzePartitionTableByConcurrencyInDynamic(t *testing.T) {
tk.MustQuery("show stats_topn where partition_name = 'global' and table_name = 't'").CheckAt([]int{5, 6}, expected)
}
}

func TestMergeGlobalStatsWithUnAnalyzedPartition(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("set tidb_partition_prune_mode=dynamic;")
tk.MustExec("CREATE TABLE `t` ( `id` int(11) DEFAULT NULL, `a` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL, `c` int(11) DEFAULT NULL ) PARTITION BY RANGE (`id`) (PARTITION `p0` VALUES LESS THAN (3), PARTITION `p1` VALUES LESS THAN (7), PARTITION `p2` VALUES LESS THAN (11));")
tk.MustExec("insert into t values (1,1,1,1),(2,2,2,2),(4,4,4,4),(5,5,5,5),(6,6,6,6),(8,8,8,8),(9,9,9,9);")
tk.MustExec("create index idxa on t (a);")
tk.MustExec("create index idxb on t (b);")
tk.MustExec("create index idxc on t (c);")
tk.MustExec("analyze table t partition p0 index idxa;")
tk.MustExec("analyze table t partition p1 index idxb;")
tk.MustExec("analyze table t partition p2 index idxc;")
tk.MustQuery("show warnings").Check(testkit.Rows(
"Warning 1105 The version 2 would collect all statistics not only the selected indexes",
"Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.t's partition p2"))
tk.MustExec("analyze table t partition p0;")
tk.MustQuery("show warnings").Check(testkit.Rows(
"Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.t's partition p0"))
}
12 changes: 11 additions & 1 deletion statistics/handle/handle.go
Original file line number Diff line number Diff line change
Expand Up @@ -775,7 +775,17 @@ func (h *Handle) mergePartitionStats2GlobalStats(sc sessionctx.Context,
allPartitionStats[partitionID] = partitionStats
}
for i := 0; i < globalStats.Num; i++ {
_, hg, cms, topN, fms := partitionStats.GetStatsInfo(histIDs[i], isIndex == 1)
_, hg, cms, topN, fms, analyzed := partitionStats.GetStatsInfo(histIDs[i], isIndex == 1)
if !analyzed {
var errMsg string
if isIndex == 0 {
errMsg = fmt.Sprintf("`%s`", tableInfo.Name.L)
} else {
errMsg = fmt.Sprintf("`%s` index: `%s`", tableInfo.Name.L, tableInfo.FindIndexNameByID(histIDs[0]))
}
err = types.ErrPartitionStatsMissing.GenWithStackByArgs(errMsg)
return
}
// partition stats is not empty but column stats(hist, topn) is missing
if partitionStats.Count > 0 && (hg == nil || hg.TotalRowCount() <= 0) && (topN == nil || topN.TotalCount() <= 0) {
var errMsg string
Expand Down
10 changes: 5 additions & 5 deletions statistics/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -377,19 +377,19 @@ func (t *Table) ColumnByName(colName string) *Column {
}

// GetStatsInfo returns their statistics according to the ID of the column or index, including histogram, CMSketch, TopN and FMSketch.
func (t *Table) GetStatsInfo(ID int64, isIndex bool) (int64, *Histogram, *CMSketch, *TopN, *FMSketch) {
func (t *Table) GetStatsInfo(ID int64, isIndex bool) (int64, *Histogram, *CMSketch, *TopN, *FMSketch, bool) {
if isIndex {
if idxStatsInfo, ok := t.Indices[ID]; ok {
return int64(idxStatsInfo.TotalRowCount()), idxStatsInfo.Histogram.Copy(), idxStatsInfo.CMSketch.Copy(), idxStatsInfo.TopN.Copy(), idxStatsInfo.FMSketch.Copy()
return int64(idxStatsInfo.TotalRowCount()), idxStatsInfo.Histogram.Copy(), idxStatsInfo.CMSketch.Copy(), idxStatsInfo.TopN.Copy(), idxStatsInfo.FMSketch.Copy(), true
}
// newly added index which is not analyzed yet
return 0, nil, nil, nil, nil
return 0, nil, nil, nil, nil, false
}
if colStatsInfo, ok := t.Columns[ID]; ok {
return int64(colStatsInfo.TotalRowCount()), colStatsInfo.Histogram.Copy(), colStatsInfo.CMSketch.Copy(), colStatsInfo.TopN.Copy(), colStatsInfo.FMSketch.Copy()
return int64(colStatsInfo.TotalRowCount()), colStatsInfo.Histogram.Copy(), colStatsInfo.CMSketch.Copy(), colStatsInfo.TopN.Copy(), colStatsInfo.FMSketch.Copy(), true
}
// newly added column which is not analyzed yet
return 0, nil, nil, nil, nil
return 0, nil, nil, nil, nil, false
}

// GetColRowCount tries to get the row count of the a column if possible.
Expand Down

0 comments on commit 6af4e4b

Please sign in to comment.