Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stats: use local feedback for partition table #7963

Merged
merged 4 commits into from
Oct 23, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 18 additions & 18 deletions statistics/feedback.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,18 @@ type feedback struct {
// QueryFeedback is used to represent the query feedback info. It contains the query's scan ranges and number of rows
// in each range.
type QueryFeedback struct {
tableID int64
hist *Histogram
tp int
feedback []feedback
expected int64 // expected is the expected scan count of corresponding query.
actual int64 // actual is the actual scan count of corresponding query.
valid bool // valid represents the whether this query feedback is still valid.
desc bool // desc represents the corresponding query is desc scan.
physicalID int64
hist *Histogram
tp int
feedback []feedback
expected int64 // expected is the expected scan count of corresponding query.
actual int64 // actual is the actual scan count of corresponding query.
valid bool // valid represents the whether this query feedback is still valid.
desc bool // desc represents the corresponding query is desc scan.
}

// NewQueryFeedback returns a new query feedback.
func NewQueryFeedback(tableID int64, hist *Histogram, expected int64, desc bool) *QueryFeedback {
func NewQueryFeedback(physicalID int64, hist *Histogram, expected int64, desc bool) *QueryFeedback {
if hist != nil && hist.Len() == 0 {
hist = nil
}
Expand All @@ -68,12 +68,12 @@ func NewQueryFeedback(tableID int64, hist *Histogram, expected int64, desc bool)
tp = indexType
}
return &QueryFeedback{
tableID: tableID,
valid: true,
tp: tp,
hist: hist,
expected: expected,
desc: desc,
physicalID: physicalID,
valid: true,
tp: tp,
hist: hist,
expected: expected,
desc: desc,
}
}

Expand Down Expand Up @@ -802,7 +802,7 @@ func (q *QueryFeedback) Equal(rq *QueryFeedback) bool {

// recalculateExpectCount recalculates the expect row count if the origin row count is estimated by pseudo.
func (q *QueryFeedback) recalculateExpectCount(h *Handle) error {
t, ok := h.statsCache.Load().(statsCache)[q.tableID]
t, ok := h.statsCache.Load().(statsCache)[q.physicalID]
if !ok {
return nil
}
Expand Down Expand Up @@ -957,7 +957,7 @@ func logForIndex(prefix string, t *Table, idx *Index, ranges []*ranger.Range, ac
}

func (q *QueryFeedback) logDetailedInfo(h *Handle) {
t, ok := h.statsCache.Load().(statsCache)[q.tableID]
t, ok := h.statsCache.Load().(statsCache)[q.physicalID]
if !ok {
return
}
Expand Down Expand Up @@ -1033,7 +1033,7 @@ func dumpFeedbackForIndex(h *Handle, q *QueryFeedback, t *Table) error {
}
colName := idx.Info.Columns[rangePosition].Name.L
var rangeCount float64
rangeFB := &QueryFeedback{tableID: q.tableID}
rangeFB := &QueryFeedback{physicalID: q.physicalID}
// prefer index stats over column stats
if idx := t.indexStartWithColumn(colName); idx != nil && idx.Histogram.Len() != 0 {
rangeCount, err = t.GetRowCountByIndexRanges(sc, idx.ID, []*ranger.Range{&rang})
Expand Down
12 changes: 7 additions & 5 deletions statistics/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ func (s *SessionStatsCollector) StoreQueryFeedback(feedback interface{}, h *Hand
s.Lock()
defer s.Unlock()
isIndex := q.tp == indexType
s.rateMap.update(q.tableID, q.hist.ID, rate, isIndex)
s.rateMap.update(q.physicalID, q.hist.ID, rate, isIndex)
if len(s.feedback) < MaxQueryFeedbackCount {
s.feedback = append(s.feedback, q)
}
Expand Down Expand Up @@ -367,7 +367,7 @@ func (h *Handle) DumpStatsFeedbackToKV() error {
if fb.tp == pkType {
err = h.dumpFeedbackToKV(fb)
} else {
t, ok := h.statsCache.Load().(statsCache)[fb.tableID]
t, ok := h.statsCache.Load().(statsCache)[fb.physicalID]
if ok {
err = dumpFeedbackForIndex(h, fb, t)
}
Expand All @@ -392,7 +392,7 @@ func (h *Handle) dumpFeedbackToKV(fb *QueryFeedback) error {
isIndex = 1
}
sql := fmt.Sprintf("insert into mysql.stats_feedback (table_id, hist_id, is_index, feedback) values "+
"(%d, %d, %d, X'%X')", fb.tableID, fb.hist.ID, isIndex, vals)
"(%d, %d, %d, X'%X')", fb.physicalID, fb.hist.ID, isIndex, vals)
h.mu.Lock()
_, err = h.mu.ctx.(sqlexec.SQLExecutor).Execute(context.TODO(), sql)
h.mu.Unlock()
Expand All @@ -416,11 +416,13 @@ func (h *Handle) UpdateStatsByLocalFeedback(is infoschema.InfoSchema) {
}
h.listHead.Unlock()
for _, fb := range h.feedback {
table, ok := is.TableByID(fb.tableID)
h.mu.Lock()
table, ok := h.getTableByPhysicalID(is, fb.physicalID)
h.mu.Unlock()
if !ok {
continue
}
tblStats := h.GetTableStats(table.Meta())
tblStats := h.GetPartitionStats(table.Meta(), fb.physicalID)
newTblStats := tblStats.copy()
if fb.tp == indexType {
idx, ok := tblStats.Indices[fb.hist.ID]
Expand Down
35 changes: 35 additions & 0 deletions statistics/update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -949,6 +949,41 @@ func (s *testStatsUpdateSuite) TestUpdateStatsByLocalFeedback(c *C) {
h.UpdateStatsByLocalFeedback(s.do.InfoSchema())
}

func (s *testStatsUpdateSuite) TestUpdatePartitionStatsByLocalFeedback(c *C) {
defer cleanEnv(c, s.store, s.do)
testKit := testkit.NewTestKit(c, s.store)
testKit.MustExec("use test")
testKit.MustExec("set @@session.tidb_enable_table_partition=1")
testKit.MustExec("create table t (a bigint(64), b bigint(64), primary key(a)) partition by range (a) (partition p0 values less than (6))")
testKit.MustExec("insert into t values (1,2),(2,2),(4,5)")
testKit.MustExec("analyze table t")
testKit.MustExec("insert into t values (3,5)")
h := s.do.StatsHandle()

oriProbability := statistics.FeedbackProbability
defer func() {
statistics.FeedbackProbability = oriProbability
}()
statistics.FeedbackProbability = 1

is := s.do.InfoSchema()
table, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t"))
c.Assert(err, IsNil)

testKit.MustQuery("select * from t where a > 1")

h.UpdateStatsByLocalFeedback(s.do.InfoSchema())

tblInfo := table.Meta()
pid := tblInfo.Partition.Definitions[0].ID
tbl := h.GetPartitionStats(tblInfo, pid)

c.Assert(tbl.Columns[tblInfo.Columns[0].ID].ToString(0), Equals, "column:1 ndv:3 totColSize:0\n"+
"num: 1 lower_bound: 1 upper_bound: 1 repeats: 1\n"+
"num: 1 lower_bound: 2 upper_bound: 2 repeats: 1\n"+
"num: 2 lower_bound: 3 upper_bound: 9223372036854775807 repeats: 0")
}

type logHook struct {
results string
}
Expand Down