stats: refine stats delta update (#6808)
This commit is contained in:
@ -660,6 +660,7 @@ func (do *Domain) updateStatsWorker(ctx sessionctx.Context, owner owner.Manager)
|
||||
log.Debug("[stats] update stats info fail: ", errors.ErrorStack(err))
|
||||
}
|
||||
case <-do.exit:
|
||||
statsHandle.FlushStats()
|
||||
do.wg.Done()
|
||||
return
|
||||
// This channel is sent only by ddl owner or the drop stats executor.
|
||||
@ -681,7 +682,7 @@ func (do *Domain) updateStatsWorker(ctx sessionctx.Context, owner owner.Manager)
|
||||
log.Debug("[stats] save meta to storage fail: ", errors.ErrorStack(err))
|
||||
}
|
||||
case <-deltaUpdateTicker.C:
|
||||
err = statsHandle.DumpStatsDeltaToKV()
|
||||
err = statsHandle.DumpStatsDeltaToKV(statistics.DumpDelta)
|
||||
if err != nil {
|
||||
log.Debug("[stats] dump stats delta fail: ", errors.ErrorStack(err))
|
||||
}
|
||||
|
||||
@ -16,6 +16,7 @@ package executor_test
|
||||
import (
|
||||
. "github.com/pingcap/check"
|
||||
"github.com/pingcap/tidb/session"
|
||||
"github.com/pingcap/tidb/statistics"
|
||||
"github.com/pingcap/tidb/util/testkit"
|
||||
)
|
||||
|
||||
@ -74,17 +75,17 @@ func (s *testSuite) TestShowStatsHealthy(c *C) {
|
||||
tk.MustQuery("show stats_healthy").Check(testkit.Rows("test t 100"))
|
||||
tk.MustExec("insert into t values (1), (2)")
|
||||
do, _ := session.GetDomain(s.store)
|
||||
do.StatsHandle().DumpStatsDeltaToKV()
|
||||
do.StatsHandle().DumpStatsDeltaToKV(statistics.DumpAll)
|
||||
tk.MustExec("analyze table t")
|
||||
tk.MustQuery("show stats_healthy").Check(testkit.Rows("test t 100"))
|
||||
tk.MustExec("insert into t values (3), (4), (5), (6), (7), (8), (9), (10)")
|
||||
do.StatsHandle().DumpStatsDeltaToKV()
|
||||
do.StatsHandle().DumpStatsDeltaToKV(statistics.DumpAll)
|
||||
do.StatsHandle().Update(do.InfoSchema())
|
||||
tk.MustQuery("show stats_healthy").Check(testkit.Rows("test t 19"))
|
||||
tk.MustExec("analyze table t")
|
||||
tk.MustQuery("show stats_healthy").Check(testkit.Rows("test t 100"))
|
||||
tk.MustExec("delete from t")
|
||||
do.StatsHandle().DumpStatsDeltaToKV()
|
||||
do.StatsHandle().DumpStatsDeltaToKV(statistics.DumpAll)
|
||||
do.StatsHandle().Update(do.InfoSchema())
|
||||
tk.MustQuery("show stats_healthy").Check(testkit.Rows("test t 0"))
|
||||
}
|
||||
|
||||
@ -16,6 +16,7 @@ package infoschema_test
|
||||
import (
|
||||
. "github.com/pingcap/check"
|
||||
"github.com/pingcap/tidb/session"
|
||||
"github.com/pingcap/tidb/statistics"
|
||||
"github.com/pingcap/tidb/store/mockstore"
|
||||
"github.com/pingcap/tidb/util/auth"
|
||||
"github.com/pingcap/tidb/util/testkit"
|
||||
@ -42,22 +43,22 @@ func (s *testSuite) TestDataForTableRowsCountField(c *C) {
|
||||
tk.MustQuery("select table_rows from information_schema.tables where table_name='t'").Check(
|
||||
testkit.Rows("0"))
|
||||
tk.MustExec("insert into t(c, d) values(1, 2), (2, 3), (3, 4)")
|
||||
h.DumpStatsDeltaToKV()
|
||||
h.DumpStatsDeltaToKV(statistics.DumpAll)
|
||||
h.Update(is)
|
||||
tk.MustQuery("select table_rows from information_schema.tables where table_name='t'").Check(
|
||||
testkit.Rows("3"))
|
||||
tk.MustExec("insert into t(c, d) values(4, 5)")
|
||||
h.DumpStatsDeltaToKV()
|
||||
h.DumpStatsDeltaToKV(statistics.DumpAll)
|
||||
h.Update(is)
|
||||
tk.MustQuery("select table_rows from information_schema.tables where table_name='t'").Check(
|
||||
testkit.Rows("4"))
|
||||
tk.MustExec("delete from t where c >= 3")
|
||||
h.DumpStatsDeltaToKV()
|
||||
h.DumpStatsDeltaToKV(statistics.DumpAll)
|
||||
h.Update(is)
|
||||
tk.MustQuery("select table_rows from information_schema.tables where table_name='t'").Check(
|
||||
testkit.Rows("2"))
|
||||
tk.MustExec("delete from t where c=3")
|
||||
h.DumpStatsDeltaToKV()
|
||||
h.DumpStatsDeltaToKV(statistics.DumpAll)
|
||||
h.Update(is)
|
||||
tk.MustQuery("select table_rows from information_schema.tables where table_name='t'").Check(
|
||||
testkit.Rows("2"))
|
||||
|
||||
@ -25,6 +25,7 @@ import (
|
||||
"github.com/pingcap/tidb/plan"
|
||||
"github.com/pingcap/tidb/session"
|
||||
"github.com/pingcap/tidb/sessionctx"
|
||||
"github.com/pingcap/tidb/statistics"
|
||||
"github.com/pingcap/tidb/store/mockstore"
|
||||
"github.com/pingcap/tidb/util/testkit"
|
||||
"github.com/pingcap/tidb/util/testleak"
|
||||
@ -53,7 +54,7 @@ func (s *testAnalyzeSuite) TestCBOWithoutAnalyze(c *C) {
|
||||
c.Assert(h.HandleDDLEvent(<-h.DDLEventCh()), IsNil)
|
||||
testKit.MustExec("insert into t1 values (1), (2), (3), (4), (5), (6)")
|
||||
testKit.MustExec("insert into t2 values (1), (2), (3), (4), (5), (6)")
|
||||
h.DumpStatsDeltaToKV()
|
||||
h.DumpStatsDeltaToKV(statistics.DumpAll)
|
||||
c.Assert(h.Update(dom.InfoSchema()), IsNil)
|
||||
testKit.MustQuery("explain select * from t1, t2 where t1.a = t2.a").Check(testkit.Rows(
|
||||
"TableScan_10 cop table:t1, range:[-inf,+inf], keep order:false 6.00",
|
||||
@ -139,7 +140,7 @@ func (s *testAnalyzeSuite) TestTableDual(c *C) {
|
||||
testKit.MustExec("insert into t values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10)")
|
||||
c.Assert(h.HandleDDLEvent(<-h.DDLEventCh()), IsNil)
|
||||
|
||||
h.DumpStatsDeltaToKV()
|
||||
h.DumpStatsDeltaToKV(statistics.DumpAll)
|
||||
c.Assert(h.Update(dom.InfoSchema()), IsNil)
|
||||
|
||||
testKit.MustQuery(`explain select * from t where 1 = 0`).Check(testkit.Rows(
|
||||
@ -170,12 +171,12 @@ func (s *testAnalyzeSuite) TestEstimation(c *C) {
|
||||
testKit.MustExec("insert into t select * from t")
|
||||
h := dom.StatsHandle()
|
||||
h.HandleDDLEvent(<-h.DDLEventCh())
|
||||
h.DumpStatsDeltaToKV()
|
||||
h.DumpStatsDeltaToKV(statistics.DumpAll)
|
||||
testKit.MustExec("analyze table t")
|
||||
for i := 1; i <= 8; i++ {
|
||||
testKit.MustExec("delete from t where a = ?", i)
|
||||
}
|
||||
h.DumpStatsDeltaToKV()
|
||||
h.DumpStatsDeltaToKV(statistics.DumpAll)
|
||||
c.Assert(h.Update(dom.InfoSchema()), IsNil)
|
||||
testKit.MustQuery("explain select count(*) from t group by a").Check(testkit.Rows(
|
||||
"TableScan_8 HashAgg_5 cop table:t, range:[-inf,+inf], keep order:false 8.00",
|
||||
@ -486,12 +487,12 @@ func (s *testAnalyzeSuite) TestOutdatedAnalyze(c *C) {
|
||||
}
|
||||
h := dom.StatsHandle()
|
||||
h.HandleDDLEvent(<-h.DDLEventCh())
|
||||
h.DumpStatsDeltaToKV()
|
||||
h.DumpStatsDeltaToKV(statistics.DumpAll)
|
||||
testKit.MustExec("analyze table t")
|
||||
testKit.MustExec("insert into t select * from t")
|
||||
testKit.MustExec("insert into t select * from t")
|
||||
testKit.MustExec("insert into t select * from t")
|
||||
h.DumpStatsDeltaToKV()
|
||||
h.DumpStatsDeltaToKV(statistics.DumpAll)
|
||||
c.Assert(h.Update(dom.InfoSchema()), IsNil)
|
||||
plan.RatioOfPseudoEstimate = 10.0
|
||||
testKit.MustQuery("explain select * from t where a <= 5 and b <= 5").Check(testkit.Rows(
|
||||
|
||||
@ -27,6 +27,7 @@ import (
|
||||
"github.com/pingcap/tidb/domain"
|
||||
"github.com/pingcap/tidb/kv"
|
||||
"github.com/pingcap/tidb/session"
|
||||
"github.com/pingcap/tidb/statistics"
|
||||
"github.com/pingcap/tidb/store/mockstore"
|
||||
"github.com/pingcap/tidb/store/mockstore/mocktikv"
|
||||
)
|
||||
@ -118,11 +119,11 @@ func (ds *testDumpStatsSuite) prepareData(c *C) {
|
||||
h.HandleDDLEvent(<-h.DDLEventCh())
|
||||
dbt.mustExec("create index c on test (a, b)")
|
||||
dbt.mustExec("insert test values (1, 's')")
|
||||
c.Assert(h.DumpStatsDeltaToKV(), IsNil)
|
||||
c.Assert(h.DumpStatsDeltaToKV(statistics.DumpAll), IsNil)
|
||||
dbt.mustExec("analyze table test")
|
||||
dbt.mustExec("insert into test(a,b) values (1, 'v'),(3, 'vvv'),(5, 'vv')")
|
||||
is := ds.sh.do.InfoSchema()
|
||||
c.Assert(h.DumpStatsDeltaToKV(), IsNil)
|
||||
c.Assert(h.DumpStatsDeltaToKV(statistics.DumpAll), IsNil)
|
||||
c.Assert(h.Update(is), IsNil)
|
||||
}
|
||||
|
||||
|
||||
@ -561,9 +561,10 @@ const (
|
||||
|
||||
// TableDelta stands for the changed count for one table.
|
||||
type TableDelta struct {
|
||||
Delta int64
|
||||
Count int64
|
||||
ColSize map[int64]int64
|
||||
Delta int64
|
||||
Count int64
|
||||
ColSize map[int64]int64
|
||||
InitTime time.Time // InitTime is the time that this delta is generated.
|
||||
}
|
||||
|
||||
// Concurrency defines concurrency values.
|
||||
|
||||
@ -18,6 +18,7 @@ import (
|
||||
"github.com/pingcap/tidb/domain"
|
||||
"github.com/pingcap/tidb/kv"
|
||||
"github.com/pingcap/tidb/model"
|
||||
"github.com/pingcap/tidb/statistics"
|
||||
"github.com/pingcap/tidb/util/testkit"
|
||||
"github.com/pingcap/tidb/util/testleak"
|
||||
)
|
||||
@ -54,7 +55,7 @@ func (s *testDumpStatsSuite) TestConversion(c *C) {
|
||||
tk.MustExec("insert into t(a,b) values (1, 1),(3, 1),(5, 10)")
|
||||
is := s.do.InfoSchema()
|
||||
h := s.do.StatsHandle()
|
||||
h.DumpStatsDeltaToKV()
|
||||
h.DumpStatsDeltaToKV(statistics.DumpAll)
|
||||
h.Update(is)
|
||||
|
||||
tableInfo, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t"))
|
||||
|
||||
@ -214,3 +214,27 @@ func (h *Handle) LoadNeededHistograms() error {
|
||||
func (h *Handle) LoadMetaCh() chan *LoadMeta {
|
||||
return h.loadMetaCh
|
||||
}
|
||||
|
||||
// FlushStats flushes the cached stats update into store.
|
||||
func (h *Handle) FlushStats() {
|
||||
for len(h.ddlEventCh) > 0 {
|
||||
e := <-h.ddlEventCh
|
||||
if err := h.HandleDDLEvent(e); err != nil {
|
||||
log.Debug("[stats] handle ddl event fail: ", errors.ErrorStack(err))
|
||||
}
|
||||
}
|
||||
if err := h.DumpStatsDeltaToKV(DumpAll); err != nil {
|
||||
log.Debug("[stats] dump stats delta fail: ", errors.ErrorStack(err))
|
||||
}
|
||||
for len(h.analyzeResultCh) > 0 {
|
||||
t := <-h.analyzeResultCh
|
||||
for i, hg := range t.Hist {
|
||||
if err := SaveStatsToStorage(h.ctx, t.TableID, t.Count, t.IsIndex, hg, t.Cms[i]); err != nil {
|
||||
log.Debug("[stats] save histogram to storage fail: ", errors.ErrorStack(err))
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := h.DumpStatsFeedbackToKV(); err != nil {
|
||||
log.Debug("[stats] dump stats feedback fail: ", errors.ErrorStack(err))
|
||||
}
|
||||
}
|
||||
|
||||
@ -339,7 +339,7 @@ func (s *testStatsCacheSuite) TestLoadHist(c *C) {
|
||||
for i := 0; i < rowCount; i++ {
|
||||
testKit.MustExec("insert into t values('bb','sdfga')")
|
||||
}
|
||||
h.DumpStatsDeltaToKV()
|
||||
h.DumpStatsDeltaToKV(statistics.DumpAll)
|
||||
h.Update(do.InfoSchema())
|
||||
newStatsTbl := h.GetTableStats(tableInfo)
|
||||
// The stats table is updated.
|
||||
|
||||
@ -156,15 +156,56 @@ func (h *Handle) NewSessionStatsCollector() *SessionStatsCollector {
|
||||
return newCollector
|
||||
}
|
||||
|
||||
// DumpStatsDeltaToKV sweeps the whole list and updates the global map. Then we dumps every table that held in map to KV.
|
||||
func (h *Handle) DumpStatsDeltaToKV() error {
|
||||
var (
|
||||
// DumpStatsDeltaRatio is the lower bound of `Modify Count / Table Count` for stats delta to be dumped.
|
||||
DumpStatsDeltaRatio = 1 / 10000.0
|
||||
// dumpStatsMaxDuration is the max duration since last update.
|
||||
dumpStatsMaxDuration = time.Hour
|
||||
)
|
||||
|
||||
// needDumpStatsDelta returns true when only updates a small portion of the table and the time since last update
|
||||
// do not exceed one hour.
|
||||
func needDumpStatsDelta(h *Handle, id int64, item variable.TableDelta, currentTime time.Time) bool {
|
||||
if item.InitTime.IsZero() {
|
||||
item.InitTime = currentTime
|
||||
}
|
||||
tbl, ok := h.statsCache.Load().(statsCache)[id]
|
||||
if !ok {
|
||||
// No need to dump if the stats is invalid.
|
||||
return false
|
||||
}
|
||||
if currentTime.Sub(item.InitTime) > dumpStatsMaxDuration {
|
||||
// Dump the stats to kv at least once an hour.
|
||||
return true
|
||||
}
|
||||
if tbl.Count == 0 || float64(item.Count)/float64(tbl.Count) > DumpStatsDeltaRatio {
|
||||
// Dump the stats when there are many modifications.
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
const (
|
||||
// DumpAll indicates dump all the delta info in to kv
|
||||
DumpAll = true
|
||||
// DumpDelta indicates dump part of the delta info in to kv.
|
||||
DumpDelta = false
|
||||
)
|
||||
|
||||
// DumpStatsDeltaToKV sweeps the whole list and updates the global map, then we dumps every table that held in map to KV.
|
||||
// If the `dumpAll` is false, it will only dump that delta info that `Modify Count / Table Count` greater than a ratio.
|
||||
func (h *Handle) DumpStatsDeltaToKV(dumpMode bool) error {
|
||||
h.listHead.Lock()
|
||||
for collector := h.listHead.next; collector != nil; collector = collector.next {
|
||||
collector.tryToRemoveFromList()
|
||||
h.merge(collector)
|
||||
}
|
||||
h.listHead.Unlock()
|
||||
currentTime := time.Now()
|
||||
for id, item := range h.globalMap {
|
||||
if dumpMode == DumpDelta && !needDumpStatsDelta(h, id, item, currentTime) {
|
||||
continue
|
||||
}
|
||||
updated, err := h.dumpTableStatCountToKV(id, item)
|
||||
if err != nil {
|
||||
return errors.Trace(err)
|
||||
|
||||
@ -31,7 +31,7 @@ func (s *testUpdateListSuite) TestInsertAndDelete(c *C) {
|
||||
items[0].Delete() // delete tail
|
||||
items[2].Delete() // delete middle
|
||||
items[4].Delete() // delete head
|
||||
h.DumpStatsDeltaToKV()
|
||||
h.DumpStatsDeltaToKV(DumpAll)
|
||||
|
||||
c.Assert(h.listHead.next, Equals, items[3])
|
||||
c.Assert(items[3].next, Equals, items[1])
|
||||
@ -42,6 +42,6 @@ func (s *testUpdateListSuite) TestInsertAndDelete(c *C) {
|
||||
// delete rest
|
||||
items[1].Delete()
|
||||
items[3].Delete()
|
||||
h.DumpStatsDeltaToKV()
|
||||
h.DumpStatsDeltaToKV(DumpAll)
|
||||
c.Assert(h.listHead.next, IsNil)
|
||||
}
|
||||
|
||||
@ -75,7 +75,7 @@ func (s *testStatsUpdateSuite) TestSingleSessionInsert(c *C) {
|
||||
h.HandleDDLEvent(<-h.DDLEventCh())
|
||||
h.HandleDDLEvent(<-h.DDLEventCh())
|
||||
|
||||
h.DumpStatsDeltaToKV()
|
||||
h.DumpStatsDeltaToKV(statistics.DumpAll)
|
||||
h.Update(is)
|
||||
stats1 := h.GetTableStats(tableInfo1)
|
||||
c.Assert(stats1.Count, Equals, int64(rowCount1))
|
||||
@ -91,7 +91,7 @@ func (s *testStatsUpdateSuite) TestSingleSessionInsert(c *C) {
|
||||
for i := 0; i < rowCount1; i++ {
|
||||
testKit.MustExec("insert into t1 values(1, 2)")
|
||||
}
|
||||
h.DumpStatsDeltaToKV()
|
||||
h.DumpStatsDeltaToKV(statistics.DumpAll)
|
||||
h.Update(is)
|
||||
stats1 = h.GetTableStats(tableInfo1)
|
||||
c.Assert(stats1.Count, Equals, int64(rowCount1*2))
|
||||
@ -106,7 +106,7 @@ func (s *testStatsUpdateSuite) TestSingleSessionInsert(c *C) {
|
||||
testKit.MustExec("insert into t1 values(1, 2)")
|
||||
}
|
||||
testKit.MustExec("commit")
|
||||
h.DumpStatsDeltaToKV()
|
||||
h.DumpStatsDeltaToKV(statistics.DumpAll)
|
||||
h.Update(is)
|
||||
stats1 = h.GetTableStats(tableInfo1)
|
||||
c.Assert(stats1.Count, Equals, int64(rowCount1*3))
|
||||
@ -122,7 +122,7 @@ func (s *testStatsUpdateSuite) TestSingleSessionInsert(c *C) {
|
||||
testKit.MustExec("update t2 set c2 = c1")
|
||||
}
|
||||
testKit.MustExec("commit")
|
||||
h.DumpStatsDeltaToKV()
|
||||
h.DumpStatsDeltaToKV(statistics.DumpAll)
|
||||
h.Update(is)
|
||||
stats1 = h.GetTableStats(tableInfo1)
|
||||
c.Assert(stats1.Count, Equals, int64(rowCount1*3))
|
||||
@ -132,7 +132,7 @@ func (s *testStatsUpdateSuite) TestSingleSessionInsert(c *C) {
|
||||
testKit.MustExec("begin")
|
||||
testKit.MustExec("delete from t1")
|
||||
testKit.MustExec("commit")
|
||||
h.DumpStatsDeltaToKV()
|
||||
h.DumpStatsDeltaToKV(statistics.DumpAll)
|
||||
h.Update(is)
|
||||
stats1 = h.GetTableStats(tableInfo1)
|
||||
c.Assert(stats1.Count, Equals, int64(0))
|
||||
@ -142,6 +142,33 @@ func (s *testStatsUpdateSuite) TestSingleSessionInsert(c *C) {
|
||||
|
||||
rs = testKit.MustQuery("select tot_col_size from mysql.stats_histograms")
|
||||
rs.Check(testkit.Rows("0", "0", "10", "10"))
|
||||
|
||||
// test dump delta only when `modify count / count` is greater than the ratio.
|
||||
originValue := statistics.DumpStatsDeltaRatio
|
||||
statistics.DumpStatsDeltaRatio = 0.5
|
||||
defer func() {
|
||||
statistics.DumpStatsDeltaRatio = originValue
|
||||
}()
|
||||
statistics.DumpStatsDeltaRatio = 0.5
|
||||
for i := 0; i < rowCount1; i++ {
|
||||
testKit.MustExec("insert into t1 values (1,2)")
|
||||
}
|
||||
h.DumpStatsDeltaToKV(statistics.DumpDelta)
|
||||
h.Update(is)
|
||||
stats1 = h.GetTableStats(tableInfo1)
|
||||
c.Assert(stats1.Count, Equals, int64(rowCount1))
|
||||
|
||||
// not dumped
|
||||
testKit.MustExec("insert into t1 values (1,2)")
|
||||
h.DumpStatsDeltaToKV(statistics.DumpDelta)
|
||||
h.Update(is)
|
||||
stats1 = h.GetTableStats(tableInfo1)
|
||||
c.Assert(stats1.Count, Equals, int64(rowCount1))
|
||||
|
||||
h.FlushStats()
|
||||
h.Update(is)
|
||||
stats1 = h.GetTableStats(tableInfo1)
|
||||
c.Assert(stats1.Count, Equals, int64(rowCount1+1))
|
||||
}
|
||||
|
||||
func (s *testStatsUpdateSuite) TestRollback(c *C) {
|
||||
@ -159,7 +186,7 @@ func (s *testStatsUpdateSuite) TestRollback(c *C) {
|
||||
tableInfo := tbl.Meta()
|
||||
h := s.do.StatsHandle()
|
||||
h.HandleDDLEvent(<-h.DDLEventCh())
|
||||
h.DumpStatsDeltaToKV()
|
||||
h.DumpStatsDeltaToKV(statistics.DumpAll)
|
||||
h.Update(is)
|
||||
|
||||
stats := h.GetTableStats(tableInfo)
|
||||
@ -194,7 +221,7 @@ func (s *testStatsUpdateSuite) TestMultiSession(c *C) {
|
||||
|
||||
h.HandleDDLEvent(<-h.DDLEventCh())
|
||||
|
||||
h.DumpStatsDeltaToKV()
|
||||
h.DumpStatsDeltaToKV(statistics.DumpAll)
|
||||
h.Update(is)
|
||||
stats1 := h.GetTableStats(tableInfo1)
|
||||
c.Assert(stats1.Count, Equals, int64(rowCount1))
|
||||
@ -214,7 +241,7 @@ func (s *testStatsUpdateSuite) TestMultiSession(c *C) {
|
||||
testKit.Se.Close()
|
||||
testKit2.Se.Close()
|
||||
|
||||
h.DumpStatsDeltaToKV()
|
||||
h.DumpStatsDeltaToKV(statistics.DumpAll)
|
||||
h.Update(is)
|
||||
stats1 = h.GetTableStats(tableInfo1)
|
||||
c.Assert(stats1.Count, Equals, int64(rowCount1*2))
|
||||
@ -243,14 +270,14 @@ func (s *testStatsUpdateSuite) TestTxnWithFailure(c *C) {
|
||||
for i := 0; i < rowCount1; i++ {
|
||||
testKit.MustExec("insert into t1 values(?, 2)", i)
|
||||
}
|
||||
h.DumpStatsDeltaToKV()
|
||||
h.DumpStatsDeltaToKV(statistics.DumpAll)
|
||||
h.Update(is)
|
||||
stats1 := h.GetTableStats(tableInfo1)
|
||||
// have not commit
|
||||
c.Assert(stats1.Count, Equals, int64(0))
|
||||
testKit.MustExec("commit")
|
||||
|
||||
h.DumpStatsDeltaToKV()
|
||||
h.DumpStatsDeltaToKV(statistics.DumpAll)
|
||||
h.Update(is)
|
||||
stats1 = h.GetTableStats(tableInfo1)
|
||||
c.Assert(stats1.Count, Equals, int64(rowCount1))
|
||||
@ -258,13 +285,13 @@ func (s *testStatsUpdateSuite) TestTxnWithFailure(c *C) {
|
||||
_, err = testKit.Exec("insert into t1 values(0, 2)")
|
||||
c.Assert(err, NotNil)
|
||||
|
||||
h.DumpStatsDeltaToKV()
|
||||
h.DumpStatsDeltaToKV(statistics.DumpAll)
|
||||
h.Update(is)
|
||||
stats1 = h.GetTableStats(tableInfo1)
|
||||
c.Assert(stats1.Count, Equals, int64(rowCount1))
|
||||
|
||||
testKit.MustExec("insert into t1 values(-1, 2)")
|
||||
h.DumpStatsDeltaToKV()
|
||||
h.DumpStatsDeltaToKV(statistics.DumpAll)
|
||||
h.Update(is)
|
||||
stats1 = h.GetTableStats(tableInfo1)
|
||||
c.Assert(stats1.Count, Equals, int64(rowCount1+1))
|
||||
@ -297,7 +324,7 @@ func (s *testStatsUpdateSuite) TestAutoUpdate(c *C) {
|
||||
|
||||
_, err = testKit.Exec("insert into t values ('ss')")
|
||||
c.Assert(err, IsNil)
|
||||
h.DumpStatsDeltaToKV()
|
||||
h.DumpStatsDeltaToKV(statistics.DumpAll)
|
||||
h.Update(is)
|
||||
err = h.HandleAutoAnalyze(is)
|
||||
c.Assert(err, IsNil)
|
||||
@ -313,7 +340,7 @@ func (s *testStatsUpdateSuite) TestAutoUpdate(c *C) {
|
||||
|
||||
_, err = testKit.Exec("insert into t values ('fff')")
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(h.DumpStatsDeltaToKV(), IsNil)
|
||||
c.Assert(h.DumpStatsDeltaToKV(statistics.DumpAll), IsNil)
|
||||
c.Assert(h.Update(is), IsNil)
|
||||
err = h.HandleAutoAnalyze(is)
|
||||
c.Assert(err, IsNil)
|
||||
@ -324,7 +351,7 @@ func (s *testStatsUpdateSuite) TestAutoUpdate(c *C) {
|
||||
|
||||
_, err = testKit.Exec("insert into t values ('fff')")
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(h.DumpStatsDeltaToKV(), IsNil)
|
||||
c.Assert(h.DumpStatsDeltaToKV(statistics.DumpAll), IsNil)
|
||||
c.Assert(h.Update(is), IsNil)
|
||||
err = h.HandleAutoAnalyze(is)
|
||||
c.Assert(err, IsNil)
|
||||
@ -335,7 +362,7 @@ func (s *testStatsUpdateSuite) TestAutoUpdate(c *C) {
|
||||
|
||||
_, err = testKit.Exec("insert into t values ('eee')")
|
||||
c.Assert(err, IsNil)
|
||||
h.DumpStatsDeltaToKV()
|
||||
h.DumpStatsDeltaToKV(statistics.DumpAll)
|
||||
h.Clear()
|
||||
// We set `Lease` here so that `Update` will use load by need strategy.
|
||||
h.Lease = time.Second
|
||||
@ -482,7 +509,7 @@ func (s *testStatsUpdateSuite) TestQueryFeedback(c *C) {
|
||||
table, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t"))
|
||||
for i, t := range tests {
|
||||
testKit.MustQuery(t.sql)
|
||||
c.Assert(h.DumpStatsDeltaToKV(), IsNil)
|
||||
c.Assert(h.DumpStatsDeltaToKV(statistics.DumpAll), IsNil)
|
||||
c.Assert(h.DumpStatsFeedbackToKV(), IsNil)
|
||||
c.Assert(h.HandleUpdateStats(s.do.InfoSchema()), IsNil)
|
||||
c.Assert(err, IsNil)
|
||||
@ -498,7 +525,7 @@ func (s *testStatsUpdateSuite) TestQueryFeedback(c *C) {
|
||||
|
||||
// Feedback from limit executor may not be accurate.
|
||||
testKit.MustQuery("select * from t where t.a <= 2 limit 1")
|
||||
h.DumpStatsDeltaToKV()
|
||||
h.DumpStatsDeltaToKV(statistics.DumpAll)
|
||||
feedback := h.GetQueryFeedback()
|
||||
c.Assert(len(feedback), Equals, 0)
|
||||
|
||||
@ -506,7 +533,7 @@ func (s *testStatsUpdateSuite) TestQueryFeedback(c *C) {
|
||||
statistics.MaxNumberOfRanges = 0
|
||||
for _, t := range tests {
|
||||
testKit.MustQuery(t.sql)
|
||||
h.DumpStatsDeltaToKV()
|
||||
h.DumpStatsDeltaToKV(statistics.DumpAll)
|
||||
feedback := h.GetQueryFeedback()
|
||||
c.Assert(len(feedback), Equals, 0)
|
||||
}
|
||||
@ -516,7 +543,7 @@ func (s *testStatsUpdateSuite) TestQueryFeedback(c *C) {
|
||||
statistics.MaxNumberOfRanges = oriNumber
|
||||
for _, t := range tests {
|
||||
testKit.MustQuery(t.sql)
|
||||
h.DumpStatsDeltaToKV()
|
||||
h.DumpStatsDeltaToKV(statistics.DumpAll)
|
||||
feedback := h.GetQueryFeedback()
|
||||
c.Assert(len(feedback), Equals, 0)
|
||||
}
|
||||
@ -554,16 +581,16 @@ func (s *testStatsUpdateSuite) TestOutOfOrderUpdate(c *C) {
|
||||
|
||||
// Simulate the case that another tidb has inserted some value, but delta info has not been dumped to kv yet.
|
||||
testKit.MustExec("insert into t values (2,2),(4,5)")
|
||||
c.Assert(h.DumpStatsDeltaToKV(), IsNil)
|
||||
c.Assert(h.DumpStatsDeltaToKV(statistics.DumpAll), IsNil)
|
||||
testKit.MustExec(fmt.Sprintf("update mysql.stats_meta set count = 1 where table_id = %d", tableInfo.ID))
|
||||
|
||||
testKit.MustExec("delete from t")
|
||||
c.Assert(h.DumpStatsDeltaToKV(), IsNil)
|
||||
c.Assert(h.DumpStatsDeltaToKV(statistics.DumpAll), IsNil)
|
||||
testKit.MustQuery("select count from mysql.stats_meta").Check(testkit.Rows("1"))
|
||||
|
||||
// Now another tidb has updated the delta info.
|
||||
testKit.MustExec(fmt.Sprintf("update mysql.stats_meta set count = 3 where table_id = %d", tableInfo.ID))
|
||||
|
||||
c.Assert(h.DumpStatsDeltaToKV(), IsNil)
|
||||
c.Assert(h.DumpStatsDeltaToKV(statistics.DumpAll), IsNil)
|
||||
testKit.MustQuery("select count from mysql.stats_meta").Check(testkit.Rows("0"))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user