From ae6d59b3be2e118bf85399c491c4c239f7d66335 Mon Sep 17 00:00:00 2001 From: Ti Chi Robot Date: Mon, 11 Sep 2023 16:33:13 +0800 Subject: [PATCH] statistics, planner: use the correct `IndexInfo` in `GenerateHistCollFromColumnInfo()` | tidb-test=pr/2211 (#44441) (#46728) close pingcap/tidb#44369 --- planner/core/stats.go | 4 ++-- statistics/integration_test.go | 16 ++++++++++++++++ statistics/selectivity_test.go | 4 ++-- statistics/table.go | 25 +++++++++++++------------ 4 files changed, 33 insertions(+), 16 deletions(-) diff --git a/planner/core/stats.go b/planner/core/stats.go index b91a9266340ed..0e466add5c7a6 100644 --- a/planner/core/stats.go +++ b/planner/core/stats.go @@ -67,7 +67,7 @@ func (p *LogicalMemTable) DeriveStats(_ []*property.StatsInfo, selfSchema *expre stats := &property.StatsInfo{ RowCount: float64(statsTable.Count), 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 { @@ -256,7 +256,7 @@ func (ds *DataSource) initStats(colGroups [][]*expression.Column) { tableStats := &property.StatsInfo{ RowCount: float64(ds.statisticTable.Count), 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 494d5204191f0..05c8ed9ac98a2 100644 --- a/statistics/integration_test.go +++ b/statistics/integration_test.go @@ -771,3 +771,19 @@ func TestIndexJoinInnerRowCountUpperBound(t *testing.T) { " └─TableRowIDScan 1000000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", )) } + +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 3cd5211fc1c8d..fca2f9261c632 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 d1461c290819e..15bcd6af535fc 100644 --- a/statistics/table.go +++ b/statistics/table.go @@ -845,19 +845,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. @@ -865,13 +859,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 }