From bdc464010dc8015fc6c49bc232476e1138fcda5c Mon Sep 17 00:00:00 2001 From: Ti Chi Robot Date: Mon, 11 Sep 2023 19:00:13 +0800 Subject: [PATCH] statistics, planner: use the correct `IndexInfo` in `GenerateHistCollFromColumnInfo()` | tidb-test=pr/2149 (#44441) (#46729) close pingcap/tidb#44369 --- planner/core/stats.go | 4 ++-- statistics/integration_test.go | 18 ++++++++++++++++++ statistics/selectivity_test.go | 4 ++-- statistics/table.go | 27 ++++++++++++++------------- 4 files changed, 36 insertions(+), 17 deletions(-) diff --git a/planner/core/stats.go b/planner/core/stats.go index 4b7ac3e33d00a..4a657e042a017 100644 --- a/planner/core/stats.go +++ b/planner/core/stats.go @@ -65,7 +65,7 @@ func (p *LogicalMemTable) DeriveStats(childStats []*property.StatsInfo, selfSche 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 { @@ -232,7 +232,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 e2a52d6401ad3..ec3c99e0b14b2 100644 --- a/statistics/integration_test.go +++ b/statistics/integration_test.go @@ -559,3 +559,21 @@ func hasPseudoStats(rows [][]interface{}) bool { } return false } + +func TestIssue44369(t *testing.T) { + store, dom, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + + 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 c96781db61b51..ede727cfa2742 100644 --- a/statistics/selectivity_test.go +++ b/statistics/selectivity_test.go @@ -557,7 +557,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) @@ -675,7 +675,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 b8bfa8d9aaf5e..b1ec7cbf3ab65 100644 --- a/statistics/table.go +++ b/statistics/table.go @@ -491,20 +491,14 @@ func (coll *HistColl) ID2UniqueID(columns []*expression.Column) *HistColl { return newColl } -// GenerateHistCollFromColumnInfo generates a new HistColl whose ColID2IdxID and IdxID2ColIDs is built from the given parameter. -func (coll *HistColl) GenerateHistCollFromColumnInfo(infos []*model.ColumnInfo, columns []*expression.Column) *HistColl { +// GenerateHistCollFromColumnInfo generates a new HistColl whose ColID2IdxIDs and IdxID2ColIDs is built from the given parameter. +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. @@ -512,13 +506,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) colID2IdxID := 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 }