diff --git a/planner/core/stats.go b/planner/core/stats.go index 6cec73209ce55..42b14cfa95e9d 100644 --- a/planner/core/stats.go +++ b/planner/core/stats.go @@ -70,7 +70,7 @@ func (p *LogicalMemTable) DeriveStats(_ []*property.StatsInfo, selfSchema *expre stats := &property.StatsInfo{ RowCount: float64(statsTable.RealtimeCount), ColNDVs: make(map[int64]float64, len(p.TableInfo.Columns)), - HistColl: statsTable.GenerateHistCollFromColumnInfo(p.TableInfo.Columns, p.schema.Columns), + HistColl: statsTable.GenerateHistCollFromColumnInfo(p.TableInfo, p.schema.Columns), StatsVersion: statistics.PseudoVersion, } for _, col := range selfSchema.Columns { @@ -289,7 +289,7 @@ func (ds *DataSource) initStats(colGroups [][]*expression.Column) { tableStats := &property.StatsInfo{ RowCount: float64(ds.statisticTable.RealtimeCount), ColNDVs: make(map[int64]float64, ds.schema.Len()), - HistColl: ds.statisticTable.GenerateHistCollFromColumnInfo(ds.Columns, ds.schema.Columns), + HistColl: ds.statisticTable.GenerateHistCollFromColumnInfo(ds.tableInfo, ds.schema.Columns), StatsVersion: ds.statisticTable.Version, } if ds.statisticTable.Pseudo { diff --git a/statistics/integration_test.go b/statistics/integration_test.go index 403d310694ca8..210e14e23d5ec 100644 --- a/statistics/integration_test.go +++ b/statistics/integration_test.go @@ -873,3 +873,19 @@ func TestOrderingIdxSelectivityThreshold(t *testing.T) { testKit.MustQuery(input[i]).Check(testkit.Rows(output[i].Result...)) } } + +func TestIssue44369(t *testing.T) { + store, dom := testkit.CreateMockStoreAndDomain(t) + h := dom.StatsHandle() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t(a int, b int, index iab(a,b));") + require.NoError(t, h.HandleDDLEvent(<-h.DDLEventCh())) + tk.MustExec("insert into t value(1,1);") + require.NoError(t, h.DumpStatsDeltaToKV(handle.DumpAll)) + tk.MustExec("analyze table t;") + is := dom.InfoSchema() + require.NoError(t, h.Update(is)) + tk.MustExec("alter table t rename column b to bb;") + tk.MustExec("select * from t where a = 10 and bb > 20;") +} diff --git a/statistics/selectivity_test.go b/statistics/selectivity_test.go index e3db3ecaf7960..03ac9ae59ff21 100644 --- a/statistics/selectivity_test.go +++ b/statistics/selectivity_test.go @@ -574,7 +574,7 @@ func TestSelectivity(t *testing.T) { sel := p.(plannercore.LogicalPlan).Children()[0].(*plannercore.LogicalSelection) ds := sel.Children()[0].(*plannercore.DataSource) - histColl := statsTbl.GenerateHistCollFromColumnInfo(ds.Columns, ds.Schema().Columns) + histColl := statsTbl.GenerateHistCollFromColumnInfo(ds.TableInfo(), ds.Schema().Columns) ratio, _, err := histColl.Selectivity(sctx, sel.Conditions, nil) require.NoErrorf(t, err, "for %s", tt.exprs) @@ -687,7 +687,7 @@ func TestDNFCondSelectivity(t *testing.T) { sel := p.(plannercore.LogicalPlan).Children()[0].(*plannercore.LogicalSelection) ds := sel.Children()[0].(*plannercore.DataSource) - histColl := statsTbl.GenerateHistCollFromColumnInfo(ds.Columns, ds.Schema().Columns) + histColl := statsTbl.GenerateHistCollFromColumnInfo(ds.TableInfo(), ds.Schema().Columns) ratio, _, err := histColl.Selectivity(sctx, sel.Conditions, nil) require.NoErrorf(t, err, "error %v, for expr %s", err, tt) diff --git a/statistics/table.go b/statistics/table.go index df65f42fce5fe..f63b600f339f0 100644 --- a/statistics/table.go +++ b/statistics/table.go @@ -939,19 +939,13 @@ func (coll *HistColl) ID2UniqueID(columns []*expression.Column) *HistColl { } // GenerateHistCollFromColumnInfo generates a new HistColl whose ColID2IdxIDs and IdxID2ColIDs is built from the given parameter. -func (coll *HistColl) GenerateHistCollFromColumnInfo(infos []*model.ColumnInfo, columns []*expression.Column) *HistColl { +func (coll *HistColl) GenerateHistCollFromColumnInfo(tblInfo *model.TableInfo, columns []*expression.Column) *HistColl { newColHistMap := make(map[int64]*Column) colInfoID2UniqueID := make(map[int64]int64, len(columns)) - colNames2UniqueID := make(map[string]int64) + idxID2idxInfo := make(map[int64]*model.IndexInfo) for _, col := range columns { colInfoID2UniqueID[col.ID] = col.UniqueID } - for _, colInfo := range infos { - uniqueID, ok := colInfoID2UniqueID[colInfo.ID] - if ok { - colNames2UniqueID[colInfo.Name.L] = uniqueID - } - } for id, colHist := range coll.Columns { uniqueID, ok := colInfoID2UniqueID[id] // Collect the statistics by the given columns. @@ -959,13 +953,20 @@ func (coll *HistColl) GenerateHistCollFromColumnInfo(infos []*model.ColumnInfo, newColHistMap[uniqueID] = colHist } } + for _, idxInfo := range tblInfo.Indices { + idxID2idxInfo[idxInfo.ID] = idxInfo + } newIdxHistMap := make(map[int64]*Index) idx2Columns := make(map[int64][]int64) colID2IdxIDs := make(map[int64][]int64) - for _, idxHist := range coll.Indices { - ids := make([]int64, 0, len(idxHist.Info.Columns)) - for _, idxCol := range idxHist.Info.Columns { - uniqueID, ok := colNames2UniqueID[idxCol.Name.L] + for id, idxHist := range coll.Indices { + idxInfo := idxID2idxInfo[id] + if idxInfo == nil { + continue + } + ids := make([]int64, 0, len(idxInfo.Columns)) + for _, idxCol := range idxInfo.Columns { + uniqueID, ok := colInfoID2UniqueID[tblInfo.Columns[idxCol.Offset].ID] if !ok { break } diff --git a/statistics/trace_test.go b/statistics/trace_test.go index 04045bda743c1..4022a448e50f8 100644 --- a/statistics/trace_test.go +++ b/statistics/trace_test.go @@ -221,9 +221,9 @@ func TestTraceDebugSelectivity(t *testing.T) { // Collect common information for the following tests. p := parser.New() - dsColInfos := make([][]*model.ColumnInfo, 0, len(in)) dsSchemaCols := make([][]*expression.Column, 0, len(in)) selConditions := make([][]expression.Expression, 0, len(in)) + tblInfos := make([]*model.TableInfo, 0, len(in)) for _, sql := range in { stmt, err := p.ParseOneStmt(sql, "", "") require.NoError(t, err) @@ -236,9 +236,9 @@ func TestTraceDebugSelectivity(t *testing.T) { sel := p.(plannercore.LogicalPlan).Children()[0].(*plannercore.LogicalSelection) ds := sel.Children()[0].(*plannercore.DataSource) - dsColInfos = append(dsColInfos, ds.Columns) dsSchemaCols = append(dsSchemaCols, ds.Schema().Columns) selConditions = append(selConditions, sel.Conditions) + tblInfos = append(tblInfos, ds.TableInfo()) } var buf bytes.Buffer encoder := json.NewEncoder(&buf) @@ -247,7 +247,7 @@ func TestTraceDebugSelectivity(t *testing.T) { // Test using ver2 stats. for i, sql := range in { stmtCtx.OptimizerDebugTrace = nil - histColl := statsTbl.GenerateHistCollFromColumnInfo(dsColInfos[i], dsSchemaCols[i]) + histColl := statsTbl.GenerateHistCollFromColumnInfo(tblInfos[i], dsSchemaCols[i]) _, _, err = histColl.Selectivity(sctx, selConditions[i], nil) require.NoError(t, err, sql, "For ver2") traceInfo := stmtCtx.OptimizerDebugTrace @@ -271,7 +271,7 @@ func TestTraceDebugSelectivity(t *testing.T) { stmtCtx.EnableOptimizerDebugTrace = true for i, sql := range in { stmtCtx.OptimizerDebugTrace = nil - histColl := statsTbl.GenerateHistCollFromColumnInfo(dsColInfos[i], dsSchemaCols[i]) + histColl := statsTbl.GenerateHistCollFromColumnInfo(tblInfos[i], dsSchemaCols[i]) _, _, err = histColl.Selectivity(sctx, selConditions[i], nil) require.NoError(t, err, sql, "For ver1") traceInfo := stmtCtx.OptimizerDebugTrace