diff --git a/executor/analyze_test.go b/executor/analyze_test.go index a6cb236b4b97c..21ad8cc2c6015 100644 --- a/executor/analyze_test.go +++ b/executor/analyze_test.go @@ -3282,3 +3282,83 @@ PARTITION BY RANGE ( a ) ( require.Greater(t, tbl.Version, lastVersion) require.Equal(t, 2, len(tbl.Indices[tableInfo.Indices[0].ID].Buckets)) } + +func TestIssue35056(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set @@session.tidb_analyze_version = 1") + createTable := `CREATE TABLE t (id int, a int, b varchar(10)) +PARTITION BY RANGE ( id ) ( + PARTITION p0 VALUES LESS THAN (10), + PARTITION p1 VALUES LESS THAN (20) +)` + tk.MustExec(createTable) + tk.MustExec("set @@session.tidb_partition_prune_mode = 'static'") + tk.MustExec("insert into t values (1,1,1),(2,2,2),(3,3,3),(4,4,4),(7,7,7),(9,9,9)") + tk.MustExec("insert into t values (11,11,11),(12,12,12),(14,14,14)") + h := dom.StatsHandle() + oriLease := h.Lease() + h.SetLease(1) + defer func() { + h.SetLease(oriLease) + }() + is := dom.InfoSchema() + h.HandleAutoAnalyze(is) + tk.MustExec("create index idxa on t (a)") + tk.MustExec("create index idxb on t (b)") + table, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + tableInfo := table.Meta() + pi := tableInfo.GetPartitionInfo() + require.NotNil(t, pi) + tk.MustExec("analyze table t partition p0 index idxa") + tk.MustExec("analyze table t partition p1 index idxb") + tk.MustExec("set @@session.tidb_partition_prune_mode = 'dynamic'") + tk.MustExec("analyze table t partition p0") + tk.MustQuery("show warnings").Sort().Check(testkit.Rows( + "Warning 8244 Build table: `t` column: `id` global-level stats failed due to missing partition-level column stats, please run analyze table to refresh columns of all partitions", + "Warning 8244 Build table: `t` index: `idxa` global-level stats failed due to missing partition-level column stats, please run analyze table to refresh columns of all partitions", + )) +} + +func TestIssue35056Related(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set @@session.tidb_analyze_version = 2") + createTable := `CREATE TABLE t (id int) +PARTITION BY RANGE ( id ) ( + PARTITION p0 VALUES LESS THAN (10), + PARTITION p1 VALUES LESS THAN (20) +)` + tk.MustExec(createTable) + tk.MustExec("set @@session.tidb_partition_prune_mode = 'static'") + tk.MustExec("insert into t values (1),(2),(3),(4),(7),(9)") + tk.MustExec("insert into t values (11),(12),(14)") + h := dom.StatsHandle() + oriLease := h.Lease() + h.SetLease(1) + defer func() { + h.SetLease(oriLease) + }() + is := dom.InfoSchema() + h.HandleAutoAnalyze(is) + tk.MustExec("alter table t add column a int") + tk.MustExec("alter table t add column b int") + table, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + tableInfo := table.Meta() + pi := tableInfo.GetPartitionInfo() + require.NotNil(t, pi) + tk.MustExec("analyze table t partition p0 columns id,a") + tk.MustExec("analyze table t partition p1 columns id,b") + tk.MustExec("set @@session.tidb_partition_prune_mode = 'dynamic'") + tk.MustExec("analyze table t partition p0") + tk.MustQuery("show warnings").Sort().Check(testkit.Rows( + "Note 1105 Analyze use auto adjusted sample rate 1.000000 for table test.t's partition p0", + "Warning 8244 Build table: `t` column: `a` global-level stats failed due to missing partition-level column stats, please run analyze table to refresh columns of all partitions", + )) +} diff --git a/statistics/table.go b/statistics/table.go index 86a21cd956442..134ea0ced5c7f 100644 --- a/statistics/table.go +++ b/statistics/table.go @@ -298,11 +298,17 @@ 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) { if isIndex { - idxStatsInfo := t.Indices[ID] - return int64(idxStatsInfo.TotalRowCount()), idxStatsInfo.Histogram.Copy(), idxStatsInfo.CMSketch.Copy(), idxStatsInfo.TopN.Copy(), idxStatsInfo.FMSketch.Copy() + if idxStatsInfo, ok := t.Indices[ID]; ok { + return int64(idxStatsInfo.TotalRowCount()), idxStatsInfo.Histogram.Copy(), idxStatsInfo.CMSketch.Copy(), idxStatsInfo.TopN.Copy(), idxStatsInfo.FMSketch.Copy() + } + // newly added index which is not analyzed yet + return 0, nil, nil, nil, nil + } + if colStatsInfo, ok := t.Columns[ID]; ok { + return int64(colStatsInfo.TotalRowCount()), colStatsInfo.Histogram.Copy(), colStatsInfo.CMSketch.Copy(), colStatsInfo.TopN.Copy(), colStatsInfo.FMSketch.Copy() } - colStatsInfo := t.Columns[ID] - return int64(colStatsInfo.TotalRowCount()), colStatsInfo.Histogram.Copy(), colStatsInfo.CMSketch.Copy(), colStatsInfo.TopN.Copy(), colStatsInfo.FMSketch.Copy() + // newly added column which is not analyzed yet + return 0, nil, nil, nil, nil } // GetColRowCount tries to get the row count of the a column if possible.