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: garbage collect stats for partition table #7962

Merged
merged 2 commits into from
Oct 24, 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
30 changes: 16 additions & 14 deletions statistics/gc.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,22 +48,24 @@ func (h *Handle) GCStats(is infoschema.InfoSchema, ddlLease time.Duration) error
return nil
}

func (h *Handle) gcTableStats(is infoschema.InfoSchema, tableID int64) error {
sql := fmt.Sprintf("select is_index, hist_id from mysql.stats_histograms where table_id = %d", tableID)
func (h *Handle) gcTableStats(is infoschema.InfoSchema, physicalID int64) error {
sql := fmt.Sprintf("select is_index, hist_id from mysql.stats_histograms where table_id = %d", physicalID)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to change the table_id in the sql text?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change needs a ddl operation and may lead to incompatibility between different version of tidb server.

rows, _, err := h.restrictedExec.ExecRestrictedSQL(nil, sql)
if err != nil {
return errors.Trace(err)
}
// The table has already been deleted in stats and acknowledged to all tidb,
// we can safely remove the meta info now.
if len(rows) == 0 {
sql := fmt.Sprintf("delete from mysql.stats_meta where table_id = %d", tableID)
sql := fmt.Sprintf("delete from mysql.stats_meta where table_id = %d", physicalID)
_, _, err := h.restrictedExec.ExecRestrictedSQL(nil, sql)
return errors.Trace(err)
}
tbl, ok := is.TableByID(tableID)
h.mu.Lock()
tbl, ok := h.getTableByPhysicalID(is, physicalID)
h.mu.Unlock()
if !ok {
return errors.Trace(h.DeleteTableStatsFromKV(tableID))
return errors.Trace(h.DeleteTableStatsFromKV(physicalID))
}
tblInfo := tbl.Meta()
for _, row := range rows {
Expand All @@ -85,7 +87,7 @@ func (h *Handle) gcTableStats(is infoschema.InfoSchema, tableID int64) error {
}
}
if !find {
if err := h.deleteHistStatsFromKV(tblInfo.ID, histID, int(isIndex)); err != nil {
if err := h.deleteHistStatsFromKV(physicalID, histID, int(isIndex)); err != nil {
return errors.Trace(err)
}
}
Expand All @@ -94,7 +96,7 @@ func (h *Handle) gcTableStats(is infoschema.InfoSchema, tableID int64) error {
}

// deleteHistStatsFromKV deletes all records about a column or an index and updates version.
func (h *Handle) deleteHistStatsFromKV(tableID int64, histID int64, isIndex int) (err error) {
func (h *Handle) deleteHistStatsFromKV(physicalID int64, histID int64, isIndex int) (err error) {
h.mu.Lock()
defer h.mu.Unlock()
exec := h.mu.ctx.(sqlexec.SQLExecutor)
Expand All @@ -106,22 +108,22 @@ func (h *Handle) deleteHistStatsFromKV(tableID int64, histID int64, isIndex int)
err = finishTransaction(context.Background(), exec, err)
}()
// First of all, we update the version. If this table doesn't exist, it won't have any problem. Because we cannot delete anything.
_, err = exec.Execute(context.Background(), fmt.Sprintf("update mysql.stats_meta set version = %d where table_id = %d ", h.mu.ctx.Txn().StartTS(), tableID))
_, err = exec.Execute(context.Background(), fmt.Sprintf("update mysql.stats_meta set version = %d where table_id = %d ", h.mu.ctx.Txn().StartTS(), physicalID))
if err != nil {
return
}
// delete histogram meta
_, err = exec.Execute(context.Background(), fmt.Sprintf("delete from mysql.stats_histograms where table_id = %d and hist_id = %d and is_index = %d", tableID, histID, isIndex))
_, err = exec.Execute(context.Background(), fmt.Sprintf("delete from mysql.stats_histograms where table_id = %d and hist_id = %d and is_index = %d", physicalID, histID, isIndex))
if err != nil {
return
}
// delete all buckets
_, err = exec.Execute(context.Background(), fmt.Sprintf("delete from mysql.stats_buckets where table_id = %d and hist_id = %d and is_index = %d", tableID, histID, isIndex))
_, err = exec.Execute(context.Background(), fmt.Sprintf("delete from mysql.stats_buckets where table_id = %d and hist_id = %d and is_index = %d", physicalID, histID, isIndex))
return
}

// DeleteTableStatsFromKV deletes table statistics from kv.
func (h *Handle) DeleteTableStatsFromKV(id int64) (err error) {
func (h *Handle) DeleteTableStatsFromKV(physicalID int64) (err error) {
h.mu.Lock()
defer h.mu.Unlock()
exec := h.mu.ctx.(sqlexec.SQLExecutor)
Expand All @@ -133,15 +135,15 @@ func (h *Handle) DeleteTableStatsFromKV(id int64) (err error) {
err = finishTransaction(context.Background(), exec, err)
}()
// We only update the version so that other tidb will know that this table is deleted.
sql := fmt.Sprintf("update mysql.stats_meta set version = %d where table_id = %d ", h.mu.ctx.Txn().StartTS(), id)
sql := fmt.Sprintf("update mysql.stats_meta set version = %d where table_id = %d ", h.mu.ctx.Txn().StartTS(), physicalID)
_, err = exec.Execute(context.Background(), sql)
if err != nil {
return
}
_, err = exec.Execute(context.Background(), fmt.Sprintf("delete from mysql.stats_histograms where table_id = %d", id))
_, err = exec.Execute(context.Background(), fmt.Sprintf("delete from mysql.stats_histograms where table_id = %d", physicalID))
if err != nil {
return
}
_, err = exec.Execute(context.Background(), fmt.Sprintf("delete from mysql.stats_buckets where table_id = %d", id))
_, err = exec.Execute(context.Background(), fmt.Sprintf("delete from mysql.stats_buckets where table_id = %d", physicalID))
return
}
36 changes: 36 additions & 0 deletions statistics/gc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,39 @@ func (s *testStatsUpdateSuite) TestGCStats(c *C) {
c.Assert(h.GCStats(s.do.InfoSchema(), ddlLease), IsNil)
testKit.MustQuery("select count(*) from mysql.stats_meta").Check(testkit.Rows("0"))
}

func (s *testStatsUpdateSuite) TestGCPartition(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), index idx(a, b))
partition by range (a) (
partition p0 values less than (3),
partition p1 values less than (6))`)
testKit.MustExec("insert into t values (1,2),(2,3),(3,4),(4,5),(5,6)")
testKit.MustExec("analyze table t")

testKit.MustQuery("select count(*) from mysql.stats_histograms").Check(testkit.Rows("6"))
testKit.MustQuery("select count(*) from mysql.stats_buckets").Check(testkit.Rows("15"))
h := s.do.StatsHandle()
h.SetLastUpdateVersion(math.MaxUint64)
ddlLease := time.Duration(0)
testKit.MustExec("alter table t drop index idx")
c.Assert(h.GCStats(s.do.InfoSchema(), ddlLease), IsNil)
testKit.MustQuery("select count(*) from mysql.stats_histograms").Check(testkit.Rows("4"))
testKit.MustQuery("select count(*) from mysql.stats_buckets").Check(testkit.Rows("10"))

testKit.MustExec("alter table t drop column b")
c.Assert(h.GCStats(s.do.InfoSchema(), ddlLease), IsNil)
testKit.MustQuery("select count(*) from mysql.stats_histograms").Check(testkit.Rows("2"))
testKit.MustQuery("select count(*) from mysql.stats_buckets").Check(testkit.Rows("5"))

testKit.MustExec("drop table t")
c.Assert(h.GCStats(s.do.InfoSchema(), ddlLease), IsNil)
testKit.MustQuery("select count(*) from mysql.stats_meta").Check(testkit.Rows("2"))
testKit.MustQuery("select count(*) from mysql.stats_histograms").Check(testkit.Rows("0"))
testKit.MustQuery("select count(*) from mysql.stats_buckets").Check(testkit.Rows("0"))
c.Assert(h.GCStats(s.do.InfoSchema(), ddlLease), IsNil)
testKit.MustQuery("select count(*) from mysql.stats_meta").Check(testkit.Rows("0"))
}