diff --git a/pkg/statistics/BUILD.bazel b/pkg/statistics/BUILD.bazel index 5c43f8191d883..20ee8a66d1270 100644 --- a/pkg/statistics/BUILD.bazel +++ b/pkg/statistics/BUILD.bazel @@ -78,7 +78,7 @@ go_test( data = glob(["testdata/**"]), embed = [":statistics"], flaky = True, - shard_count = 34, + shard_count = 35, deps = [ "//pkg/config", "//pkg/parser/ast", diff --git a/pkg/statistics/handle/history/history_stats.go b/pkg/statistics/handle/history/history_stats.go index 92f660431448c..ef6d190d24acc 100644 --- a/pkg/statistics/handle/history/history_stats.go +++ b/pkg/statistics/handle/history/history_stats.go @@ -135,10 +135,7 @@ func RecordHistoricalStatsToStorage(sctx sessionctx.Context, physicalID int64, j version = js.Version } else { for _, p := range js.Partitions { - version = p.Version - if version != 0 { - break - } + version = max(version, p.Version) } } blocks, err := storage.JSONTableToBlocks(js, maxColumnSize) @@ -147,9 +144,10 @@ func RecordHistoricalStatsToStorage(sctx sessionctx.Context, physicalID int64, j } ts := time.Now().Format("2006-01-02 15:04:05.999999") - const sql = "INSERT INTO mysql.stats_history(table_id, stats_data, seq_no, version, create_time) VALUES (%?, %?, %?, %?, %?)" + const sql = "INSERT INTO mysql.stats_history(table_id, stats_data, seq_no, version, create_time) VALUES (%?, %?, %?, %?, %?)" + + "ON DUPLICATE KEY UPDATE stats_data=%?, create_time=%?" for i := 0; i < len(blocks); i++ { - if _, err := util.Exec(sctx, sql, physicalID, blocks[i], i, version, ts); err != nil { + if _, err = util.Exec(sctx, sql, physicalID, blocks[i], i, version, ts, blocks[i], ts); err != nil { return 0, errors.Trace(err) } } diff --git a/pkg/statistics/integration_test.go b/pkg/statistics/integration_test.go index 9b51915b174c8..c675cd47f857c 100644 --- a/pkg/statistics/integration_test.go +++ b/pkg/statistics/integration_test.go @@ -23,6 +23,7 @@ import ( "time" "github.com/pingcap/failpoint" + "github.com/pingcap/tidb/pkg/config" "github.com/pingcap/tidb/pkg/parser/model" "github.com/pingcap/tidb/pkg/statistics" "github.com/pingcap/tidb/pkg/statistics/handle/autoanalyze" @@ -481,3 +482,34 @@ func TestIssue44369(t *testing.T) { tk.MustExec("alter table t rename column b to bb;") tk.MustExec("select * from t where a = 10 and bb > 20;") } + +func TestGlobalIndexWithAnalyzeVersion1AndHistoricalStats(t *testing.T) { + defer config.RestoreFunc()() + config.UpdateGlobal(func(conf *config.Config) { + conf.EnableGlobalIndex = true + }) + store, dom := testkit.CreateMockStoreAndDomain(t) + tk := testkit.NewTestKit(t, store) + + tk.MustExec("set tidb_analyze_version = 1") + tk.MustExec("set global tidb_enable_historical_stats = true") + defer tk.MustExec("set global tidb_enable_historical_stats = default") + + tk.MustExec("use test") + tk.MustExec(`CREATE TABLE t ( a int, b int, c int default 0) + PARTITION BY RANGE (a) ( + PARTITION p0 VALUES LESS THAN (10), + PARTITION p1 VALUES LESS THAN (20), + PARTITION p2 VALUES LESS THAN (30), + PARTITION p3 VALUES LESS THAN (40))`) + tk.MustExec("ALTER TABLE t ADD UNIQUE INDEX idx(b)") + tk.MustExec("INSERT INTO t(a, b) values(1, 1), (2, 2), (3, 3), (15, 15), (25, 25), (35, 35)") + + tblID := dom.MustGetTableID(t, "test", "t") + + for i := 0; i < 10; i++ { + tk.MustExec("analyze table t") + } + // Each analyze will only generate one record + tk.MustQuery(fmt.Sprintf("select count(*) from mysql.stats_history where table_id=%d", tblID)).Equal(testkit.Rows("10")) +}