From b42a6f449a49e6a68360b607a5de497a2f64faa8 Mon Sep 17 00:00:00 2001 From: rebelice Date: Mon, 8 Mar 2021 19:58:55 +0800 Subject: [PATCH] statistics: add test for analyze single partition (#23167) --- errno/errname.go | 2 +- errors.toml | 2 +- statistics/handle/handle.go | 22 +++++++++++++++++----- statistics/handle/handle_test.go | 20 ++++++++++++++++++++ 4 files changed, 39 insertions(+), 7 deletions(-) diff --git a/errno/errname.go b/errno/errname.go index bef12b1ef6e83..2de87ae39a984 100644 --- a/errno/errname.go +++ b/errno/errname.go @@ -1033,7 +1033,7 @@ var MySQLErrName = map[uint16]*mysql.ErrMessage{ ErrInvalidTableSample: mysql.Message("Invalid TABLESAMPLE: %s", nil), ErrJSONObjectKeyTooLong: mysql.Message("TiDB does not yet support JSON objects with the key length >= 65536", nil), - ErrBuildGlobalLevelStatsFailed: mysql.Message("Build global-level stats failed due to missing partition-level stats", nil), + ErrBuildGlobalLevelStatsFailed: mysql.Message("Build table: %s global-level stats failed due to missing partition-level stats", nil), ErrInvalidPlacementSpec: mysql.Message("Invalid placement policy '%s': %s", nil), ErrPlacementPolicyCheck: mysql.Message("Placement policy didn't meet the constraint, reason: %s", nil), diff --git a/errors.toml b/errors.toml index 42a91c57c36b1..335c31f002131 100644 --- a/errors.toml +++ b/errors.toml @@ -1573,7 +1573,7 @@ TiDB does not yet support JSON objects with the key length >= 65536 ["types:8131"] error = ''' -Build global-level stats failed due to missing partition-level stats +Build table: %s global-level stats failed due to missing partition-level stats ''' ["variable:1193"] diff --git a/statistics/handle/handle.go b/statistics/handle/handle.go index e3090a10ea071..68fc6aa8b5cb1 100644 --- a/statistics/handle/handle.go +++ b/statistics/handle/handle.go @@ -367,16 +367,28 @@ func (h *Handle) MergePartitionStats2GlobalStats(sc sessionctx.Context, opts map if err != nil { return } + // if the err == nil && partitionStats == nil, it means we lack the partition-level stats which the physicalID is equal to partitionID. + if partitionStats == nil { + var errMsg string + if isIndex == 0 { + errMsg = fmt.Sprintf("`%s`", tableInfo.Name.L) + } else { + indexName := "" + for _, idx := range tableInfo.Indices { + if idx.ID == idxID { + indexName = idx.Name.L + } + } + errMsg = fmt.Sprintf("`%s` index: `%s`", tableInfo.Name.L, indexName) + } + err = types.ErrBuildGlobalLevelStatsFailed.GenWithStackByArgs(errMsg) + return + } statistics.CheckAnalyzeVerOnTable(partitionStats, &statsVer) if statsVer != statistics.Version2 { // global-stats only support stats-ver2 return nil, fmt.Errorf("[stats]: global statistics for partitioned tables only available in statistics version2, please set tidb_analyze_version to 2") } - // if the err == nil && partitionStats == nil, it means we lack the partition-level stats which the physicalID is equal to partitionID. - if partitionStats == nil { - err = types.ErrBuildGlobalLevelStatsFailed - return - } for i := 0; i < globalStats.Num; i++ { ID := tableInfo.Columns[i].ID if isIndex != 0 { diff --git a/statistics/handle/handle_test.go b/statistics/handle/handle_test.go index e02369f220d35..5b58d32c90cfc 100644 --- a/statistics/handle/handle_test.go +++ b/statistics/handle/handle_test.go @@ -54,6 +54,7 @@ func cleanEnv(c *C, store kv.Storage, do *domain.Domain) { tk.MustExec("delete from mysql.stats_histograms") tk.MustExec("delete from mysql.stats_buckets") tk.MustExec("delete from mysql.stats_extended") + tk.MustExec("delete from mysql.stats_fm_sketch") tk.MustExec("delete from mysql.schema_index_usage") do.StatsHandle().Clear() } @@ -1512,6 +1513,25 @@ func (s *testStatsSuite) TestAnalyzeWithDynamicPartitionPruneMode(c *C) { c.Assert(rows[1][6], Equals, "6") } +func (s *testStatsSuite) TestFMSWithAnalyzePartition(c *C) { + defer cleanEnv(c, s.store, s.do) + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("set @@tidb_partition_prune_mode = '" + string(variable.Dynamic) + "'") + tk.MustExec("set @@tidb_analyze_version = 2") + tk.MustExec(`create table t (a int, key(a)) partition by range(a) + (partition p0 values less than (10), + partition p1 values less than (22))`) + tk.MustExec(`insert into t values (1), (2), (3), (10), (11)`) + tk.MustQuery("select count(*) from mysql.stats_fm_sketch").Check(testkit.Rows("0")) + tk.MustExec("analyze table t partition p0 with 1 topn, 2 buckets") + tk.MustQuery("show warnings").Sort().Check(testkit.Rows( + "Warning 8131 Build table: `t` global-level stats failed due to missing partition-level stats", + "Warning 8131 Build table: `t` index: `a` global-level stats failed due to missing partition-level stats", + )) + tk.MustQuery("select count(*) from mysql.stats_fm_sketch").Check(testkit.Rows("1")) +} + var _ = SerialSuites(&statsSerialSuite{}) type statsSerialSuite struct {