diff --git a/pkg/statistics/BUILD.bazel b/pkg/statistics/BUILD.bazel index 6d64b5dc37431..0e5899ebdb6d5 100644 --- a/pkg/statistics/BUILD.bazel +++ b/pkg/statistics/BUILD.bazel @@ -81,7 +81,7 @@ go_test( data = glob(["testdata/**"]), embed = [":statistics"], flaky = True, - shard_count = 37, + shard_count = 38, 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 dd71aa0b75085..03171f8e6d422 100644 --- a/pkg/statistics/handle/history/history_stats.go +++ b/pkg/statistics/handle/history/history_stats.go @@ -136,10 +136,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) @@ -148,9 +145,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 7da521264cf7b..aac15f11d274c 100644 --- a/pkg/statistics/integration_test.go +++ b/pkg/statistics/integration_test.go @@ -596,3 +596,31 @@ func TestTableLastAnalyzeVersion(t *testing.T) { require.True(t, found) require.NotEqual(t, uint64(0), statsTbl.LastAnalyzeVersion) } + +func TestGlobalIndexWithAnalyzeVersion1AndHistoricalStats(t *testing.T) { + store, dom := testkit.CreateMockStoreAndDomain(t) + tk := testkit.NewTestKit(t, store) + + tk.MustExec("set tidb_enable_global_index = true") + 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")) +}