github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/milevadb-server/statistics/handle/update_test.go (about)

     1  // Copyright 2020 WHTCORPS INC, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package handle_test
    15  
    16  import (
    17  	"fmt"
    18  	"math"
    19  	"os"
    20  	"strings"
    21  	"time"
    22  
    23  	"github.com/whtcorpsinc/BerolinaSQL/allegrosql"
    24  	"github.com/whtcorpsinc/BerolinaSQL/perceptron"
    25  	. "github.com/whtcorpsinc/check"
    26  	"github.com/whtcorpsinc/log"
    27  	"github.com/whtcorpsinc/milevadb/causetstore/einsteindb/oracle"
    28  	"github.com/whtcorpsinc/milevadb/ekv"
    29  	"github.com/whtcorpsinc/milevadb/petri"
    30  	"github.com/whtcorpsinc/milevadb/soliton/codec"
    31  	"github.com/whtcorpsinc/milevadb/soliton/ranger"
    32  	"github.com/whtcorpsinc/milevadb/soliton/testkit"
    33  	"github.com/whtcorpsinc/milevadb/soliton/testleak"
    34  	"github.com/whtcorpsinc/milevadb/statistics"
    35  	"github.com/whtcorpsinc/milevadb/statistics/handle"
    36  	"github.com/whtcorpsinc/milevadb/stochastikctx/stmtctx"
    37  	"github.com/whtcorpsinc/milevadb/stochastikctx/variable"
    38  	"github.com/whtcorpsinc/milevadb/types"
    39  	"go.uber.org/zap"
    40  	"go.uber.org/zap/zapembedded"
    41  )
    42  
    43  var _ = Suite(&testStatsSuite{})
    44  
    45  type testStatsSuite struct {
    46  	causetstore ekv.CausetStorage
    47  	do          *petri.Petri
    48  	hook        *logHook
    49  }
    50  
    51  func (s *testStatsSuite) SetUpSuite(c *C) {
    52  	testleak.BeforeTest()
    53  	// Add the hook here to avoid data race.
    54  	s.registerHook()
    55  	var err error
    56  	s.causetstore, s.do, err = newStoreWithBootstrap()
    57  	c.Assert(err, IsNil)
    58  }
    59  
    60  func (s *testStatsSuite) TearDownSuite(c *C) {
    61  	s.do.Close()
    62  	s.causetstore.Close()
    63  	testleak.AfterTest(c)()
    64  }
    65  
    66  func (s *testStatsSuite) registerHook() {
    67  	conf := &log.Config{Level: os.Getenv("log_level"), File: log.FileLogConfig{}}
    68  	_, r, _ := log.InitLogger(conf)
    69  	s.hook = &logHook{r.Core, ""}
    70  	lg := zap.New(s.hook)
    71  	log.ReplaceGlobals(lg, r)
    72  }
    73  
    74  func (s *testStatsSuite) TestSingleStochastikInsert(c *C) {
    75  	defer cleanEnv(c, s.causetstore, s.do)
    76  	testKit := testkit.NewTestKit(c, s.causetstore)
    77  	testKit.MustInterDirc("use test")
    78  	testKit.MustInterDirc("create causet t1 (c1 int, c2 int)")
    79  	testKit.MustInterDirc("create causet t2 (c1 int, c2 int)")
    80  
    81  	rowCount1 := 10
    82  	rowCount2 := 20
    83  	for i := 0; i < rowCount1; i++ {
    84  		testKit.MustInterDirc("insert into t1 values(1, 2)")
    85  	}
    86  	for i := 0; i < rowCount2; i++ {
    87  		testKit.MustInterDirc("insert into t2 values(1, 2)")
    88  	}
    89  
    90  	is := s.do.SchemaReplicant()
    91  	tbl1, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t1"))
    92  	c.Assert(err, IsNil)
    93  	blockInfo1 := tbl1.Meta()
    94  	h := s.do.StatsHandle()
    95  
    96  	h.HandleDBSEvent(<-h.DBSEventCh())
    97  	h.HandleDBSEvent(<-h.DBSEventCh())
    98  
    99  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   100  	c.Assert(h.UFIDelate(is), IsNil)
   101  	stats1 := h.GetTableStats(blockInfo1)
   102  	c.Assert(stats1.Count, Equals, int64(rowCount1))
   103  
   104  	tbl2, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t2"))
   105  	c.Assert(err, IsNil)
   106  	blockInfo2 := tbl2.Meta()
   107  	stats2 := h.GetTableStats(blockInfo2)
   108  	c.Assert(stats2.Count, Equals, int64(rowCount2))
   109  
   110  	testKit.MustInterDirc("analyze causet t1")
   111  	// Test uFIDelate in a txn.
   112  	for i := 0; i < rowCount1; i++ {
   113  		testKit.MustInterDirc("insert into t1 values(1, 2)")
   114  	}
   115  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   116  	c.Assert(h.UFIDelate(is), IsNil)
   117  	stats1 = h.GetTableStats(blockInfo1)
   118  	c.Assert(stats1.Count, Equals, int64(rowCount1*2))
   119  
   120  	// Test IncreaseFactor.
   121  	count, err := stats1.DeferredCausetEqualRowCount(testKit.Se.GetStochastikVars().StmtCtx, types.NewIntCauset(1), blockInfo1.DeferredCausets[0].ID)
   122  	c.Assert(err, IsNil)
   123  	c.Assert(count, Equals, float64(rowCount1*2))
   124  
   125  	testKit.MustInterDirc("begin")
   126  	for i := 0; i < rowCount1; i++ {
   127  		testKit.MustInterDirc("insert into t1 values(1, 2)")
   128  	}
   129  	testKit.MustInterDirc("commit")
   130  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   131  	c.Assert(h.UFIDelate(is), IsNil)
   132  	stats1 = h.GetTableStats(blockInfo1)
   133  	c.Assert(stats1.Count, Equals, int64(rowCount1*3))
   134  
   135  	testKit.MustInterDirc("begin")
   136  	for i := 0; i < rowCount1; i++ {
   137  		testKit.MustInterDirc("insert into t1 values(1, 2)")
   138  	}
   139  	for i := 0; i < rowCount1; i++ {
   140  		testKit.MustInterDirc("delete from t1 limit 1")
   141  	}
   142  	for i := 0; i < rowCount2; i++ {
   143  		testKit.MustInterDirc("uFIDelate t2 set c2 = c1")
   144  	}
   145  	testKit.MustInterDirc("commit")
   146  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   147  	c.Assert(h.UFIDelate(is), IsNil)
   148  	stats1 = h.GetTableStats(blockInfo1)
   149  	c.Assert(stats1.Count, Equals, int64(rowCount1*3))
   150  	stats2 = h.GetTableStats(blockInfo2)
   151  	c.Assert(stats2.Count, Equals, int64(rowCount2))
   152  
   153  	testKit.MustInterDirc("begin")
   154  	testKit.MustInterDirc("delete from t1")
   155  	testKit.MustInterDirc("commit")
   156  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   157  	c.Assert(h.UFIDelate(is), IsNil)
   158  	stats1 = h.GetTableStats(blockInfo1)
   159  	c.Assert(stats1.Count, Equals, int64(0))
   160  
   161  	rs := testKit.MustQuery("select modify_count from allegrosql.stats_spacetime")
   162  	rs.Check(testkit.Rows("40", "70"))
   163  
   164  	rs = testKit.MustQuery("select tot_col_size from allegrosql.stats_histograms").Sort()
   165  	rs.Check(testkit.Rows("0", "0", "20", "20"))
   166  
   167  	// test dump delta only when `modify count / count` is greater than the ratio.
   168  	originValue := handle.DumpStatsDeltaRatio
   169  	handle.DumpStatsDeltaRatio = 0.5
   170  	defer func() {
   171  		handle.DumpStatsDeltaRatio = originValue
   172  	}()
   173  	handle.DumpStatsDeltaRatio = 0.5
   174  	for i := 0; i < rowCount1; i++ {
   175  		testKit.MustInterDirc("insert into t1 values (1,2)")
   176  	}
   177  	h.DumpStatsDeltaToKV(handle.DumFIDelelta)
   178  	c.Assert(h.UFIDelate(is), IsNil)
   179  	stats1 = h.GetTableStats(blockInfo1)
   180  	c.Assert(stats1.Count, Equals, int64(rowCount1))
   181  
   182  	// not dumped
   183  	testKit.MustInterDirc("insert into t1 values (1,2)")
   184  	h.DumpStatsDeltaToKV(handle.DumFIDelelta)
   185  	c.Assert(h.UFIDelate(is), IsNil)
   186  	stats1 = h.GetTableStats(blockInfo1)
   187  	c.Assert(stats1.Count, Equals, int64(rowCount1))
   188  
   189  	h.FlushStats()
   190  	c.Assert(h.UFIDelate(is), IsNil)
   191  	stats1 = h.GetTableStats(blockInfo1)
   192  	c.Assert(stats1.Count, Equals, int64(rowCount1+1))
   193  }
   194  
   195  func (s *testStatsSuite) TestRollback(c *C) {
   196  	defer cleanEnv(c, s.causetstore, s.do)
   197  	testKit := testkit.NewTestKit(c, s.causetstore)
   198  	testKit.MustInterDirc("use test")
   199  	testKit.MustInterDirc("create causet t (a int, b int)")
   200  	testKit.MustInterDirc("begin")
   201  	testKit.MustInterDirc("insert into t values (1,2)")
   202  	testKit.MustInterDirc("rollback")
   203  
   204  	is := s.do.SchemaReplicant()
   205  	tbl, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
   206  	c.Assert(err, IsNil)
   207  	blockInfo := tbl.Meta()
   208  	h := s.do.StatsHandle()
   209  	h.HandleDBSEvent(<-h.DBSEventCh())
   210  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   211  	c.Assert(h.UFIDelate(is), IsNil)
   212  
   213  	stats := h.GetTableStats(blockInfo)
   214  	c.Assert(stats.Count, Equals, int64(0))
   215  	c.Assert(stats.ModifyCount, Equals, int64(0))
   216  }
   217  
   218  func (s *testStatsSuite) TestMultiStochastik(c *C) {
   219  	defer cleanEnv(c, s.causetstore, s.do)
   220  	testKit := testkit.NewTestKit(c, s.causetstore)
   221  	testKit.MustInterDirc("use test")
   222  	testKit.MustInterDirc("create causet t1 (c1 int, c2 int)")
   223  
   224  	rowCount1 := 10
   225  	for i := 0; i < rowCount1; i++ {
   226  		testKit.MustInterDirc("insert into t1 values(1, 2)")
   227  	}
   228  
   229  	testKit1 := testkit.NewTestKit(c, s.causetstore)
   230  	for i := 0; i < rowCount1; i++ {
   231  		testKit1.MustInterDirc("insert into test.t1 values(1, 2)")
   232  	}
   233  	testKit2 := testkit.NewTestKit(c, s.causetstore)
   234  	for i := 0; i < rowCount1; i++ {
   235  		testKit2.MustInterDirc("delete from test.t1 limit 1")
   236  	}
   237  	is := s.do.SchemaReplicant()
   238  	tbl1, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t1"))
   239  	c.Assert(err, IsNil)
   240  	blockInfo1 := tbl1.Meta()
   241  	h := s.do.StatsHandle()
   242  
   243  	h.HandleDBSEvent(<-h.DBSEventCh())
   244  
   245  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   246  	c.Assert(h.UFIDelate(is), IsNil)
   247  	stats1 := h.GetTableStats(blockInfo1)
   248  	c.Assert(stats1.Count, Equals, int64(rowCount1))
   249  
   250  	for i := 0; i < rowCount1; i++ {
   251  		testKit.MustInterDirc("insert into t1 values(1, 2)")
   252  	}
   253  
   254  	for i := 0; i < rowCount1; i++ {
   255  		testKit1.MustInterDirc("insert into test.t1 values(1, 2)")
   256  	}
   257  
   258  	for i := 0; i < rowCount1; i++ {
   259  		testKit2.MustInterDirc("delete from test.t1 limit 1")
   260  	}
   261  
   262  	testKit.Se.Close()
   263  	testKit2.Se.Close()
   264  
   265  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   266  	c.Assert(h.UFIDelate(is), IsNil)
   267  	stats1 = h.GetTableStats(blockInfo1)
   268  	c.Assert(stats1.Count, Equals, int64(rowCount1*2))
   269  	// The stochastik in testKit is already Closed, set it to nil will create a new stochastik.
   270  	testKit.Se = nil
   271  	rs := testKit.MustQuery("select modify_count from allegrosql.stats_spacetime")
   272  	rs.Check(testkit.Rows("60"))
   273  }
   274  
   275  func (s *testStatsSuite) TestTxnWithFailure(c *C) {
   276  	defer cleanEnv(c, s.causetstore, s.do)
   277  	testKit := testkit.NewTestKit(c, s.causetstore)
   278  	testKit.MustInterDirc("use test")
   279  	testKit.MustInterDirc("create causet t1 (c1 int primary key, c2 int)")
   280  
   281  	is := s.do.SchemaReplicant()
   282  	tbl1, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t1"))
   283  	c.Assert(err, IsNil)
   284  	blockInfo1 := tbl1.Meta()
   285  	h := s.do.StatsHandle()
   286  
   287  	h.HandleDBSEvent(<-h.DBSEventCh())
   288  
   289  	rowCount1 := 10
   290  	testKit.MustInterDirc("begin")
   291  	for i := 0; i < rowCount1; i++ {
   292  		testKit.MustInterDirc("insert into t1 values(?, 2)", i)
   293  	}
   294  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   295  	c.Assert(h.UFIDelate(is), IsNil)
   296  	stats1 := h.GetTableStats(blockInfo1)
   297  	// have not commit
   298  	c.Assert(stats1.Count, Equals, int64(0))
   299  	testKit.MustInterDirc("commit")
   300  
   301  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   302  	c.Assert(h.UFIDelate(is), IsNil)
   303  	stats1 = h.GetTableStats(blockInfo1)
   304  	c.Assert(stats1.Count, Equals, int64(rowCount1))
   305  
   306  	_, err = testKit.InterDirc("insert into t1 values(0, 2)")
   307  	c.Assert(err, NotNil)
   308  
   309  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   310  	c.Assert(h.UFIDelate(is), IsNil)
   311  	stats1 = h.GetTableStats(blockInfo1)
   312  	c.Assert(stats1.Count, Equals, int64(rowCount1))
   313  
   314  	testKit.MustInterDirc("insert into t1 values(-1, 2)")
   315  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   316  	c.Assert(h.UFIDelate(is), IsNil)
   317  	stats1 = h.GetTableStats(blockInfo1)
   318  	c.Assert(stats1.Count, Equals, int64(rowCount1+1))
   319  }
   320  
   321  func (s *testStatsSuite) TestUFIDelatePartition(c *C) {
   322  	defer cleanEnv(c, s.causetstore, s.do)
   323  	testKit := testkit.NewTestKit(c, s.causetstore)
   324  	testKit.MustInterDirc("use test")
   325  	testKit.MustInterDirc("drop causet if exists t")
   326  	createTable := `CREATE TABLE t (a int, b char(5)) PARTITION BY RANGE (a) (PARTITION p0 VALUES LESS THAN (6),PARTITION p1 VALUES LESS THAN (11))`
   327  	testKit.MustInterDirc(createTable)
   328  	do := s.do
   329  	is := do.SchemaReplicant()
   330  	tbl, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
   331  	c.Assert(err, IsNil)
   332  	blockInfo := tbl.Meta()
   333  	h := do.StatsHandle()
   334  	err = h.HandleDBSEvent(<-h.DBSEventCh())
   335  	c.Assert(err, IsNil)
   336  	pi := blockInfo.GetPartitionInfo()
   337  	c.Assert(len(pi.Definitions), Equals, 2)
   338  	bDefCausID := blockInfo.DeferredCausets[1].ID
   339  
   340  	testKit.MustInterDirc(`insert into t values (1, "a"), (7, "a")`)
   341  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   342  	c.Assert(h.UFIDelate(is), IsNil)
   343  	for _, def := range pi.Definitions {
   344  		statsTbl := h.GetPartitionStats(blockInfo, def.ID)
   345  		c.Assert(statsTbl.ModifyCount, Equals, int64(1))
   346  		c.Assert(statsTbl.Count, Equals, int64(1))
   347  		c.Assert(statsTbl.DeferredCausets[bDefCausID].TotDefCausSize, Equals, int64(2))
   348  	}
   349  
   350  	testKit.MustInterDirc(`uFIDelate t set a = a + 1, b = "aa"`)
   351  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   352  	c.Assert(h.UFIDelate(is), IsNil)
   353  	for _, def := range pi.Definitions {
   354  		statsTbl := h.GetPartitionStats(blockInfo, def.ID)
   355  		c.Assert(statsTbl.ModifyCount, Equals, int64(2))
   356  		c.Assert(statsTbl.Count, Equals, int64(1))
   357  		c.Assert(statsTbl.DeferredCausets[bDefCausID].TotDefCausSize, Equals, int64(3))
   358  	}
   359  
   360  	testKit.MustInterDirc("delete from t")
   361  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   362  	c.Assert(h.UFIDelate(is), IsNil)
   363  	for _, def := range pi.Definitions {
   364  		statsTbl := h.GetPartitionStats(blockInfo, def.ID)
   365  		c.Assert(statsTbl.ModifyCount, Equals, int64(3))
   366  		c.Assert(statsTbl.Count, Equals, int64(0))
   367  		c.Assert(statsTbl.DeferredCausets[bDefCausID].TotDefCausSize, Equals, int64(0))
   368  	}
   369  }
   370  
   371  func (s *testStatsSuite) TestAutoUFIDelate(c *C) {
   372  	defer cleanEnv(c, s.causetstore, s.do)
   373  	testKit := testkit.NewTestKit(c, s.causetstore)
   374  	testKit.MustInterDirc("use test")
   375  	testKit.MustInterDirc("create causet t (a varchar(20))")
   376  
   377  	handle.AutoAnalyzeMinCnt = 0
   378  	testKit.MustInterDirc("set global milevadb_auto_analyze_ratio = 0.2")
   379  	defer func() {
   380  		handle.AutoAnalyzeMinCnt = 1000
   381  		testKit.MustInterDirc("set global milevadb_auto_analyze_ratio = 0.0")
   382  	}()
   383  
   384  	do := s.do
   385  	is := do.SchemaReplicant()
   386  	tbl, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
   387  	c.Assert(err, IsNil)
   388  	blockInfo := tbl.Meta()
   389  	h := do.StatsHandle()
   390  
   391  	h.HandleDBSEvent(<-h.DBSEventCh())
   392  	c.Assert(h.UFIDelate(is), IsNil)
   393  	stats := h.GetTableStats(blockInfo)
   394  	c.Assert(stats.Count, Equals, int64(0))
   395  
   396  	_, err = testKit.InterDirc("insert into t values ('ss'), ('ss'), ('ss'), ('ss'), ('ss')")
   397  	c.Assert(err, IsNil)
   398  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   399  	c.Assert(h.UFIDelate(is), IsNil)
   400  	h.HandleAutoAnalyze(is)
   401  	c.Assert(h.UFIDelate(is), IsNil)
   402  	stats = h.GetTableStats(blockInfo)
   403  	c.Assert(stats.Count, Equals, int64(5))
   404  	c.Assert(stats.ModifyCount, Equals, int64(0))
   405  	for _, item := range stats.DeferredCausets {
   406  		// TotDefCausSize = 5*(2(length of 'ss') + 1(size of len byte)).
   407  		c.Assert(item.TotDefCausSize, Equals, int64(15))
   408  		break
   409  	}
   410  
   411  	// Test that even if the causet is recently modified, we can still analyze the causet.
   412  	h.SetLease(time.Second)
   413  	defer func() { h.SetLease(0) }()
   414  	_, err = testKit.InterDirc("insert into t values ('fff')")
   415  	c.Assert(err, IsNil)
   416  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   417  	c.Assert(h.UFIDelate(is), IsNil)
   418  	h.HandleAutoAnalyze(is)
   419  	c.Assert(h.UFIDelate(is), IsNil)
   420  	stats = h.GetTableStats(blockInfo)
   421  	c.Assert(stats.Count, Equals, int64(6))
   422  	c.Assert(stats.ModifyCount, Equals, int64(1))
   423  
   424  	_, err = testKit.InterDirc("insert into t values ('fff')")
   425  	c.Assert(err, IsNil)
   426  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   427  	c.Assert(h.UFIDelate(is), IsNil)
   428  	h.HandleAutoAnalyze(is)
   429  	c.Assert(h.UFIDelate(is), IsNil)
   430  	stats = h.GetTableStats(blockInfo)
   431  	c.Assert(stats.Count, Equals, int64(7))
   432  	c.Assert(stats.ModifyCount, Equals, int64(0))
   433  
   434  	_, err = testKit.InterDirc("insert into t values ('eee')")
   435  	c.Assert(err, IsNil)
   436  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   437  	c.Assert(h.UFIDelate(is), IsNil)
   438  	h.HandleAutoAnalyze(is)
   439  	c.Assert(h.UFIDelate(is), IsNil)
   440  	stats = h.GetTableStats(blockInfo)
   441  	c.Assert(stats.Count, Equals, int64(8))
   442  	// Modify count is non-zero means that we do not analyze the causet.
   443  	c.Assert(stats.ModifyCount, Equals, int64(1))
   444  	for _, item := range stats.DeferredCausets {
   445  		// TotDefCausSize = 27, because the causet has not been analyzed, and insert memex will add 3(length of 'eee') to TotDefCausSize.
   446  		c.Assert(item.TotDefCausSize, Equals, int64(27))
   447  		break
   448  	}
   449  
   450  	testKit.MustInterDirc("analyze causet t")
   451  	_, err = testKit.InterDirc("create index idx on t(a)")
   452  	c.Assert(err, IsNil)
   453  	is = do.SchemaReplicant()
   454  	tbl, err = is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
   455  	c.Assert(err, IsNil)
   456  	blockInfo = tbl.Meta()
   457  	h.HandleAutoAnalyze(is)
   458  	c.Assert(h.UFIDelate(is), IsNil)
   459  	stats = h.GetTableStats(blockInfo)
   460  	c.Assert(stats.Count, Equals, int64(8))
   461  	c.Assert(stats.ModifyCount, Equals, int64(0))
   462  	hg, ok := stats.Indices[blockInfo.Indices[0].ID]
   463  	c.Assert(ok, IsTrue)
   464  	c.Assert(hg.NDV, Equals, int64(3))
   465  	c.Assert(hg.Len(), Equals, 3)
   466  }
   467  
   468  func (s *testStatsSuite) TestAutoUFIDelatePartition(c *C) {
   469  	defer cleanEnv(c, s.causetstore, s.do)
   470  	testKit := testkit.NewTestKit(c, s.causetstore)
   471  	testKit.MustInterDirc("use test")
   472  	testKit.MustInterDirc("drop causet if exists t")
   473  	testKit.MustInterDirc("create causet t (a int) PARTITION BY RANGE (a) (PARTITION p0 VALUES LESS THAN (6))")
   474  	testKit.MustInterDirc("analyze causet t")
   475  
   476  	handle.AutoAnalyzeMinCnt = 0
   477  	testKit.MustInterDirc("set global milevadb_auto_analyze_ratio = 0.6")
   478  	defer func() {
   479  		handle.AutoAnalyzeMinCnt = 1000
   480  		testKit.MustInterDirc("set global milevadb_auto_analyze_ratio = 0.0")
   481  	}()
   482  
   483  	do := s.do
   484  	is := do.SchemaReplicant()
   485  	tbl, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
   486  	c.Assert(err, IsNil)
   487  	blockInfo := tbl.Meta()
   488  	pi := blockInfo.GetPartitionInfo()
   489  	h := do.StatsHandle()
   490  
   491  	c.Assert(h.UFIDelate(is), IsNil)
   492  	stats := h.GetPartitionStats(blockInfo, pi.Definitions[0].ID)
   493  	c.Assert(stats.Count, Equals, int64(0))
   494  
   495  	testKit.MustInterDirc("insert into t values (1)")
   496  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   497  	c.Assert(h.UFIDelate(is), IsNil)
   498  	h.HandleAutoAnalyze(is)
   499  	stats = h.GetPartitionStats(blockInfo, pi.Definitions[0].ID)
   500  	c.Assert(stats.Count, Equals, int64(1))
   501  	c.Assert(stats.ModifyCount, Equals, int64(0))
   502  }
   503  
   504  func (s *testStatsSuite) TestTableAnalyzed(c *C) {
   505  	defer cleanEnv(c, s.causetstore, s.do)
   506  	testKit := testkit.NewTestKit(c, s.causetstore)
   507  	testKit.MustInterDirc("use test")
   508  	testKit.MustInterDirc("create causet t (a int)")
   509  	testKit.MustInterDirc("insert into t values (1)")
   510  
   511  	is := s.do.SchemaReplicant()
   512  	tbl, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
   513  	c.Assert(err, IsNil)
   514  	blockInfo := tbl.Meta()
   515  	h := s.do.StatsHandle()
   516  
   517  	c.Assert(h.UFIDelate(is), IsNil)
   518  	statsTbl := h.GetTableStats(blockInfo)
   519  	c.Assert(handle.TableAnalyzed(statsTbl), IsFalse)
   520  
   521  	testKit.MustInterDirc("analyze causet t")
   522  	c.Assert(h.UFIDelate(is), IsNil)
   523  	statsTbl = h.GetTableStats(blockInfo)
   524  	c.Assert(handle.TableAnalyzed(statsTbl), IsTrue)
   525  
   526  	h.Clear()
   527  	oriLease := h.Lease()
   528  	// set it to non-zero so we will use load by need strategy
   529  	h.SetLease(1)
   530  	defer func() {
   531  		h.SetLease(oriLease)
   532  	}()
   533  	c.Assert(h.UFIDelate(is), IsNil)
   534  	statsTbl = h.GetTableStats(blockInfo)
   535  	c.Assert(handle.TableAnalyzed(statsTbl), IsTrue)
   536  }
   537  
   538  func (s *testStatsSuite) TestUFIDelateErrorRate(c *C) {
   539  	defer cleanEnv(c, s.causetstore, s.do)
   540  	h := s.do.StatsHandle()
   541  	is := s.do.SchemaReplicant()
   542  	h.SetLease(0)
   543  	c.Assert(h.UFIDelate(is), IsNil)
   544  	oriProbability := statistics.FeedbackProbability
   545  	oriMinLogCount := handle.MinLogScanCount
   546  	oriErrorRate := handle.MinLogErrorRate
   547  	defer func() {
   548  		statistics.FeedbackProbability = oriProbability
   549  		handle.MinLogScanCount = oriMinLogCount
   550  		handle.MinLogErrorRate = oriErrorRate
   551  	}()
   552  	statistics.FeedbackProbability.CausetStore(1)
   553  	handle.MinLogScanCount = 0
   554  	handle.MinLogErrorRate = 0
   555  
   556  	testKit := testkit.NewTestKit(c, s.causetstore)
   557  	testKit.MustInterDirc("use test")
   558  	testKit.MustInterDirc("create causet t (a bigint(64), b bigint(64), primary key(a), index idx(b))")
   559  	h.HandleDBSEvent(<-h.DBSEventCh())
   560  
   561  	testKit.MustInterDirc("insert into t values (1, 3)")
   562  
   563  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   564  	testKit.MustInterDirc("analyze causet t")
   565  
   566  	testKit.MustInterDirc("insert into t values (2, 3)")
   567  	testKit.MustInterDirc("insert into t values (5, 3)")
   568  	testKit.MustInterDirc("insert into t values (8, 3)")
   569  	testKit.MustInterDirc("insert into t values (12, 3)")
   570  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   571  	is = s.do.SchemaReplicant()
   572  	c.Assert(h.UFIDelate(is), IsNil)
   573  
   574  	causet, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
   575  	c.Assert(err, IsNil)
   576  	tblInfo := causet.Meta()
   577  	tbl := h.GetTableStats(tblInfo)
   578  	aID := tblInfo.DeferredCausets[0].ID
   579  	bID := tblInfo.Indices[0].ID
   580  
   581  	// The statistic causet is outdated now.
   582  	c.Assert(tbl.DeferredCausets[aID].NotAccurate(), IsTrue)
   583  
   584  	testKit.MustQuery("select * from t where a between 1 and 10")
   585  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   586  	c.Assert(h.DumpStatsFeedbackToKV(), IsNil)
   587  	c.Assert(h.HandleUFIDelateStats(is), IsNil)
   588  	h.UFIDelateErrorRate(is)
   589  	c.Assert(h.UFIDelate(is), IsNil)
   590  	tbl = h.GetTableStats(tblInfo)
   591  
   592  	// The error rate of this column is not larger than MaxErrorRate now.
   593  	c.Assert(tbl.DeferredCausets[aID].NotAccurate(), IsFalse)
   594  
   595  	c.Assert(tbl.Indices[bID].NotAccurate(), IsTrue)
   596  	testKit.MustQuery("select * from t where b between 2 and 10")
   597  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   598  	c.Assert(h.DumpStatsFeedbackToKV(), IsNil)
   599  	c.Assert(h.HandleUFIDelateStats(is), IsNil)
   600  	h.UFIDelateErrorRate(is)
   601  	c.Assert(h.UFIDelate(is), IsNil)
   602  	tbl = h.GetTableStats(tblInfo)
   603  	c.Assert(tbl.Indices[bID].NotAccurate(), IsFalse)
   604  	c.Assert(tbl.Indices[bID].QueryTotal, Equals, int64(1))
   605  
   606  	testKit.MustInterDirc("analyze causet t")
   607  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   608  	c.Assert(h.UFIDelate(is), IsNil)
   609  	tbl = h.GetTableStats(tblInfo)
   610  	c.Assert(tbl.Indices[bID].QueryTotal, Equals, int64(0))
   611  }
   612  
   613  func (s *testStatsSuite) TestUFIDelatePartitionErrorRate(c *C) {
   614  	defer cleanEnv(c, s.causetstore, s.do)
   615  	h := s.do.StatsHandle()
   616  	is := s.do.SchemaReplicant()
   617  	h.SetLease(0)
   618  	c.Assert(h.UFIDelate(is), IsNil)
   619  	oriProbability := statistics.FeedbackProbability
   620  	oriMinLogCount := handle.MinLogScanCount
   621  	oriErrorRate := handle.MinLogErrorRate
   622  	defer func() {
   623  		statistics.FeedbackProbability = oriProbability
   624  		handle.MinLogScanCount = oriMinLogCount
   625  		handle.MinLogErrorRate = oriErrorRate
   626  	}()
   627  	statistics.FeedbackProbability.CausetStore(1)
   628  	handle.MinLogScanCount = 0
   629  	handle.MinLogErrorRate = 0
   630  
   631  	testKit := testkit.NewTestKit(c, s.causetstore)
   632  	testKit.MustInterDirc("use test")
   633  	testKit.MustInterDirc(`set @@milevadb_partition_prune_mode='` + string(variable.StaticOnly) + `'`)
   634  	testKit.MustInterDirc("create causet t (a bigint(64), primary key(a)) partition by range (a) (partition p0 values less than (30))")
   635  	h.HandleDBSEvent(<-h.DBSEventCh())
   636  
   637  	testKit.MustInterDirc("insert into t values (1)")
   638  
   639  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   640  	testKit.MustInterDirc("analyze causet t")
   641  
   642  	testKit.MustInterDirc("insert into t values (2)")
   643  	testKit.MustInterDirc("insert into t values (5)")
   644  	testKit.MustInterDirc("insert into t values (8)")
   645  	testKit.MustInterDirc("insert into t values (12)")
   646  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   647  	is = s.do.SchemaReplicant()
   648  	c.Assert(h.UFIDelate(is), IsNil)
   649  
   650  	causet, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
   651  	c.Assert(err, IsNil)
   652  	tblInfo := causet.Meta()
   653  	pid := tblInfo.Partition.Definitions[0].ID
   654  	tbl := h.GetPartitionStats(tblInfo, pid)
   655  	aID := tblInfo.DeferredCausets[0].ID
   656  
   657  	// The statistic causet is outdated now.
   658  	c.Assert(tbl.DeferredCausets[aID].NotAccurate(), IsTrue)
   659  
   660  	testKit.MustQuery("select * from t where a between 1 and 10")
   661  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   662  	c.Assert(h.DumpStatsFeedbackToKV(), IsNil)
   663  	c.Assert(h.HandleUFIDelateStats(is), IsNil)
   664  	h.UFIDelateErrorRate(is)
   665  	c.Assert(h.UFIDelate(is), IsNil)
   666  	tbl = h.GetPartitionStats(tblInfo, pid)
   667  
   668  	// The error rate of this column is not larger than MaxErrorRate now.
   669  	c.Assert(tbl.DeferredCausets[aID].NotAccurate(), IsFalse)
   670  }
   671  
   672  func appendBucket(h *statistics.Histogram, l, r int64) {
   673  	lower, upper := types.NewIntCauset(l), types.NewIntCauset(r)
   674  	h.AppendBucket(&lower, &upper, 0, 0)
   675  }
   676  
   677  func (s *testStatsSuite) TestSplitRange(c *C) {
   678  	h := statistics.NewHistogram(0, 0, 0, 0, types.NewFieldType(allegrosql.TypeLong), 5, 0)
   679  	appendBucket(h, 1, 1)
   680  	appendBucket(h, 2, 5)
   681  	appendBucket(h, 7, 7)
   682  	appendBucket(h, 8, 8)
   683  	appendBucket(h, 10, 13)
   684  
   685  	tests := []struct {
   686  		points  []int64
   687  		exclude []bool
   688  		result  string
   689  	}{
   690  		{
   691  			points:  []int64{1, 1},
   692  			exclude: []bool{false, false},
   693  			result:  "[1,1]",
   694  		},
   695  		{
   696  			points:  []int64{0, 1, 3, 8, 8, 20},
   697  			exclude: []bool{true, false, true, false, true, false},
   698  			result:  "(0,1],(3,7),[7,8),[8,8],(8,10),[10,20]",
   699  		},
   700  		{
   701  			points:  []int64{8, 10, 20, 30},
   702  			exclude: []bool{false, false, true, true},
   703  			result:  "[8,10),[10,10],(20,30)",
   704  		},
   705  		{
   706  			// test remove invalid range
   707  			points:  []int64{8, 9},
   708  			exclude: []bool{false, true},
   709  			result:  "[8,9)",
   710  		},
   711  	}
   712  	for _, t := range tests {
   713  		ranges := make([]*ranger.Range, 0, len(t.points)/2)
   714  		for i := 0; i < len(t.points); i += 2 {
   715  			ranges = append(ranges, &ranger.Range{
   716  				LowVal:      []types.Causet{types.NewIntCauset(t.points[i])},
   717  				LowExclude:  t.exclude[i],
   718  				HighVal:     []types.Causet{types.NewIntCauset(t.points[i+1])},
   719  				HighExclude: t.exclude[i+1],
   720  			})
   721  		}
   722  		ranges, _ = h.SplitRange(nil, ranges, false)
   723  		var ranStrs []string
   724  		for _, ran := range ranges {
   725  			ranStrs = append(ranStrs, ran.String())
   726  		}
   727  		c.Assert(strings.Join(ranStrs, ","), Equals, t.result)
   728  	}
   729  }
   730  
   731  func (s *testStatsSuite) TestQueryFeedback(c *C) {
   732  	defer cleanEnv(c, s.causetstore, s.do)
   733  	testKit := testkit.NewTestKit(c, s.causetstore)
   734  	testKit.MustInterDirc("use test")
   735  	testKit.MustInterDirc("create causet t (a bigint(64), b bigint(64), primary key(a), index idx(b))")
   736  	testKit.MustInterDirc("insert into t values (1,2),(2,2),(4,5)")
   737  	testKit.MustInterDirc("analyze causet t")
   738  	testKit.MustInterDirc("insert into t values (3,4)")
   739  
   740  	h := s.do.StatsHandle()
   741  	oriProbability := statistics.FeedbackProbability
   742  	oriNumber := statistics.MaxNumberOfRanges
   743  	oriMinLogCount := handle.MinLogScanCount
   744  	oriErrorRate := handle.MinLogErrorRate
   745  	defer func() {
   746  		statistics.FeedbackProbability = oriProbability
   747  		statistics.MaxNumberOfRanges = oriNumber
   748  		handle.MinLogScanCount = oriMinLogCount
   749  		handle.MinLogErrorRate = oriErrorRate
   750  	}()
   751  	statistics.FeedbackProbability.CausetStore(1)
   752  	handle.MinLogScanCount = 0
   753  	handle.MinLogErrorRate = 0
   754  	tests := []struct {
   755  		allegrosql  string
   756  		hist        string
   757  		idxDefCauss int
   758  	}{
   759  		{
   760  			// test primary key feedback
   761  			allegrosql: "select * from t where t.a <= 5 order by a desc",
   762  			hist: "column:1 ndv:4 totDefCausSize:0\n" +
   763  				"num: 1 lower_bound: -9223372036854775808 upper_bound: 2 repeats: 0\n" +
   764  				"num: 2 lower_bound: 2 upper_bound: 4 repeats: 0\n" +
   765  				"num: 1 lower_bound: 4 upper_bound: 4 repeats: 1",
   766  			idxDefCauss: 0,
   767  		},
   768  		{
   769  			// test index feedback by double read
   770  			allegrosql: "select * from t use index(idx) where t.b <= 5",
   771  			hist: "index:1 ndv:2\n" +
   772  				"num: 3 lower_bound: -inf upper_bound: 5 repeats: 0\n" +
   773  				"num: 1 lower_bound: 5 upper_bound: 5 repeats: 1",
   774  			idxDefCauss: 1,
   775  		},
   776  		{
   777  			// test index feedback by single read
   778  			allegrosql: "select b from t use index(idx) where t.b <= 5",
   779  			hist: "index:1 ndv:2\n" +
   780  				"num: 3 lower_bound: -inf upper_bound: 5 repeats: 0\n" +
   781  				"num: 1 lower_bound: 5 upper_bound: 5 repeats: 1",
   782  			idxDefCauss: 1,
   783  		},
   784  	}
   785  	is := s.do.SchemaReplicant()
   786  	causet, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
   787  	for i, t := range tests {
   788  		testKit.MustQuery(t.allegrosql)
   789  		c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   790  		c.Assert(h.DumpStatsFeedbackToKV(), IsNil)
   791  		c.Assert(h.HandleUFIDelateStats(s.do.SchemaReplicant()), IsNil)
   792  		c.Assert(err, IsNil)
   793  		c.Assert(h.UFIDelate(is), IsNil)
   794  		tblInfo := causet.Meta()
   795  		tbl := h.GetTableStats(tblInfo)
   796  		if t.idxDefCauss == 0 {
   797  			c.Assert(tbl.DeferredCausets[tblInfo.DeferredCausets[0].ID].ToString(0), Equals, tests[i].hist)
   798  		} else {
   799  			c.Assert(tbl.Indices[tblInfo.Indices[0].ID].ToString(1), Equals, tests[i].hist)
   800  		}
   801  	}
   802  
   803  	// Feedback from limit interlock may not be accurate.
   804  	testKit.MustQuery("select * from t where t.a <= 5 limit 1")
   805  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   806  	feedback := h.GetQueryFeedback()
   807  	c.Assert(feedback.Size, Equals, 0)
   808  
   809  	// Test only collect for max number of Ranges.
   810  	statistics.MaxNumberOfRanges = 0
   811  	for _, t := range tests {
   812  		testKit.MustQuery(t.allegrosql)
   813  		c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   814  		feedback := h.GetQueryFeedback()
   815  		c.Assert(feedback.Size, Equals, 0)
   816  	}
   817  
   818  	// Test collect feedback by probability.
   819  	statistics.FeedbackProbability.CausetStore(0)
   820  	statistics.MaxNumberOfRanges = oriNumber
   821  	for _, t := range tests {
   822  		testKit.MustQuery(t.allegrosql)
   823  		c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   824  		feedback := h.GetQueryFeedback()
   825  		c.Assert(feedback.Size, Equals, 0)
   826  	}
   827  
   828  	// Test that after drop stats, the feedback won't cause panic.
   829  	statistics.FeedbackProbability.CausetStore(1)
   830  	for _, t := range tests {
   831  		testKit.MustQuery(t.allegrosql)
   832  	}
   833  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   834  	c.Assert(h.DumpStatsFeedbackToKV(), IsNil)
   835  	testKit.MustInterDirc("drop stats t")
   836  	c.Assert(h.HandleUFIDelateStats(s.do.SchemaReplicant()), IsNil)
   837  
   838  	// Test that the outdated feedback won't cause panic.
   839  	testKit.MustInterDirc("analyze causet t")
   840  	for _, t := range tests {
   841  		testKit.MustQuery(t.allegrosql)
   842  	}
   843  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   844  	c.Assert(h.DumpStatsFeedbackToKV(), IsNil)
   845  	testKit.MustInterDirc("drop causet t")
   846  	c.Assert(h.HandleUFIDelateStats(s.do.SchemaReplicant()), IsNil)
   847  }
   848  
   849  func (s *testStatsSuite) TestQueryFeedbackForPartition(c *C) {
   850  	defer cleanEnv(c, s.causetstore, s.do)
   851  	testKit := testkit.NewTestKit(c, s.causetstore)
   852  	testKit.MustInterDirc("use test")
   853  	testKit.MustInterDirc(`set @@milevadb_partition_prune_mode='` + string(variable.StaticOnly) + `'`)
   854  	testKit.MustInterDirc(`create causet t (a bigint(64), b bigint(64), primary key(a), index idx(b))
   855  			    partition by range (a) (
   856  			    partition p0 values less than (3),
   857  			    partition p1 values less than (6))`)
   858  	testKit.MustInterDirc("insert into t values (1,2),(2,2),(3,4),(4,1),(5,6)")
   859  	testKit.MustInterDirc("analyze causet t")
   860  
   861  	oriProbability := statistics.FeedbackProbability
   862  	oriMinLogCount := handle.MinLogScanCount
   863  	oriErrorRate := handle.MinLogErrorRate
   864  	defer func() {
   865  		statistics.FeedbackProbability = oriProbability
   866  		handle.MinLogScanCount = oriMinLogCount
   867  		handle.MinLogErrorRate = oriErrorRate
   868  	}()
   869  	statistics.FeedbackProbability.CausetStore(1)
   870  	handle.MinLogScanCount = 0
   871  	handle.MinLogErrorRate = 0
   872  
   873  	h := s.do.StatsHandle()
   874  	tests := []struct {
   875  		allegrosql  string
   876  		hist        string
   877  		idxDefCauss int
   878  	}{
   879  		{
   880  			// test primary key feedback
   881  			allegrosql: "select * from t where t.a <= 5",
   882  			hist: "column:1 ndv:2 totDefCausSize:0\n" +
   883  				"num: 1 lower_bound: -9223372036854775808 upper_bound: 2 repeats: 0\n" +
   884  				"num: 1 lower_bound: 2 upper_bound: 5 repeats: 0",
   885  			idxDefCauss: 0,
   886  		},
   887  		{
   888  			// test index feedback by double read
   889  			allegrosql: "select * from t use index(idx) where t.b <= 5",
   890  			hist: "index:1 ndv:1\n" +
   891  				"num: 2 lower_bound: -inf upper_bound: 6 repeats: 0",
   892  			idxDefCauss: 1,
   893  		},
   894  		{
   895  			// test index feedback by single read
   896  			allegrosql: "select b from t use index(idx) where t.b <= 5",
   897  			hist: "index:1 ndv:1\n" +
   898  				"num: 2 lower_bound: -inf upper_bound: 6 repeats: 0",
   899  			idxDefCauss: 1,
   900  		},
   901  	}
   902  	is := s.do.SchemaReplicant()
   903  	causet, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
   904  	c.Assert(err, IsNil)
   905  	tblInfo := causet.Meta()
   906  	pi := tblInfo.GetPartitionInfo()
   907  	c.Assert(pi, NotNil)
   908  
   909  	// This test will check the result of partition p0.
   910  	var pid int64
   911  	for _, def := range pi.Definitions {
   912  		if def.Name.L == "p0" {
   913  			pid = def.ID
   914  			break
   915  		}
   916  	}
   917  
   918  	for i, t := range tests {
   919  		testKit.MustQuery(t.allegrosql)
   920  		c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   921  		c.Assert(h.DumpStatsFeedbackToKV(), IsNil)
   922  		c.Assert(h.HandleUFIDelateStats(s.do.SchemaReplicant()), IsNil)
   923  		c.Assert(err, IsNil)
   924  		c.Assert(h.UFIDelate(is), IsNil)
   925  		tbl := h.GetPartitionStats(tblInfo, pid)
   926  		if t.idxDefCauss == 0 {
   927  			c.Assert(tbl.DeferredCausets[tblInfo.DeferredCausets[0].ID].ToString(0), Equals, tests[i].hist)
   928  		} else {
   929  			c.Assert(tbl.Indices[tblInfo.Indices[0].ID].ToString(1), Equals, tests[i].hist)
   930  		}
   931  	}
   932  	testKit.MustInterDirc("drop causet t")
   933  }
   934  
   935  func (s *testStatsSuite) TestUFIDelateSystemTable(c *C) {
   936  	defer cleanEnv(c, s.causetstore, s.do)
   937  	testKit := testkit.NewTestKit(c, s.causetstore)
   938  	testKit.MustInterDirc("use test")
   939  	testKit.MustInterDirc("create causet t (a int, b int)")
   940  	testKit.MustInterDirc("insert into t values (1,2)")
   941  	testKit.MustInterDirc("analyze causet t")
   942  	testKit.MustInterDirc("analyze causet allegrosql.stats_histograms")
   943  	h := s.do.StatsHandle()
   944  	c.Assert(h.UFIDelate(s.do.SchemaReplicant()), IsNil)
   945  	feedback := h.GetQueryFeedback()
   946  	// We may have query feedback for system blocks, but we do not need to causetstore them.
   947  	c.Assert(feedback.Size, Equals, 0)
   948  }
   949  
   950  func (s *testStatsSuite) TestOutOfOrderUFIDelate(c *C) {
   951  	defer cleanEnv(c, s.causetstore, s.do)
   952  	testKit := testkit.NewTestKit(c, s.causetstore)
   953  	testKit.MustInterDirc("use test")
   954  	testKit.MustInterDirc("create causet t (a int, b int)")
   955  	testKit.MustInterDirc("insert into t values (1,2)")
   956  
   957  	do := s.do
   958  	is := do.SchemaReplicant()
   959  	tbl, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
   960  	c.Assert(err, IsNil)
   961  	blockInfo := tbl.Meta()
   962  	h := do.StatsHandle()
   963  	h.HandleDBSEvent(<-h.DBSEventCh())
   964  
   965  	// Simulate the case that another milevadb has inserted some value, but delta info has not been dumped to ekv yet.
   966  	testKit.MustInterDirc("insert into t values (2,2),(4,5)")
   967  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   968  	testKit.MustInterDirc(fmt.Sprintf("uFIDelate allegrosql.stats_spacetime set count = 1 where block_id = %d", blockInfo.ID))
   969  
   970  	testKit.MustInterDirc("delete from t")
   971  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   972  	testKit.MustQuery("select count from allegrosql.stats_spacetime").Check(testkit.Rows("1"))
   973  
   974  	// Now another milevadb has uFIDelated the delta info.
   975  	testKit.MustInterDirc(fmt.Sprintf("uFIDelate allegrosql.stats_spacetime set count = 3 where block_id = %d", blockInfo.ID))
   976  
   977  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   978  	testKit.MustQuery("select count from allegrosql.stats_spacetime").Check(testkit.Rows("0"))
   979  }
   980  
   981  func (s *testStatsSuite) TestUFIDelateStatsByLocalFeedback(c *C) {
   982  	defer cleanEnv(c, s.causetstore, s.do)
   983  	testKit := testkit.NewTestKit(c, s.causetstore)
   984  	testKit.MustInterDirc("use test")
   985  	testKit.MustInterDirc(`set @@milevadb_partition_prune_mode='` + string(variable.StaticOnly) + `'`)
   986  	testKit.MustInterDirc("create causet t (a bigint(64), b bigint(64), primary key(a), index idx(b))")
   987  	testKit.MustInterDirc("insert into t values (1,2),(2,2),(4,5)")
   988  	testKit.MustInterDirc("analyze causet t")
   989  	testKit.MustInterDirc("insert into t values (3,5)")
   990  	h := s.do.StatsHandle()
   991  	oriProbability := statistics.FeedbackProbability
   992  	oriMinLogCount := handle.MinLogScanCount
   993  	oriErrorRate := handle.MinLogErrorRate
   994  	oriNumber := statistics.MaxNumberOfRanges
   995  	defer func() {
   996  		statistics.FeedbackProbability = oriProbability
   997  		handle.MinLogScanCount = oriMinLogCount
   998  		handle.MinLogErrorRate = oriErrorRate
   999  		statistics.MaxNumberOfRanges = oriNumber
  1000  	}()
  1001  	statistics.FeedbackProbability.CausetStore(1)
  1002  	handle.MinLogScanCount = 0
  1003  	handle.MinLogErrorRate = 0
  1004  
  1005  	is := s.do.SchemaReplicant()
  1006  	causet, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
  1007  	c.Assert(err, IsNil)
  1008  
  1009  	tblInfo := causet.Meta()
  1010  	h.GetTableStats(tblInfo)
  1011  
  1012  	testKit.MustQuery("select * from t use index(idx) where b <= 5")
  1013  	testKit.MustQuery("select * from t where a > 1")
  1014  	testKit.MustQuery("select * from t use index(idx) where b = 5")
  1015  
  1016  	h.UFIDelateStatsByLocalFeedback(s.do.SchemaReplicant())
  1017  	tbl := h.GetTableStats(tblInfo)
  1018  
  1019  	c.Assert(tbl.DeferredCausets[tblInfo.DeferredCausets[0].ID].ToString(0), Equals, "column:1 ndv:3 totDefCausSize:0\n"+
  1020  		"num: 1 lower_bound: 1 upper_bound: 1 repeats: 1\n"+
  1021  		"num: 2 lower_bound: 2 upper_bound: 4 repeats: 0\n"+
  1022  		"num: 1 lower_bound: 4 upper_bound: 9223372036854775807 repeats: 0")
  1023  	sc := &stmtctx.StatementContext{TimeZone: time.Local}
  1024  	low, err := codec.EncodeKey(sc, nil, types.NewIntCauset(5))
  1025  	c.Assert(err, IsNil)
  1026  
  1027  	c.Assert(tbl.Indices[tblInfo.Indices[0].ID].CMSketch.QueryBytes(low), Equals, uint64(2))
  1028  
  1029  	c.Assert(tbl.Indices[tblInfo.Indices[0].ID].ToString(1), Equals, "index:1 ndv:2\n"+
  1030  		"num: 2 lower_bound: -inf upper_bound: 5 repeats: 0\n"+
  1031  		"num: 1 lower_bound: 5 upper_bound: 5 repeats: 1")
  1032  
  1033  	// Test that it won't cause panic after uFIDelate.
  1034  	testKit.MustQuery("select * from t use index(idx) where b > 0")
  1035  
  1036  	// Test that after drop stats, it won't cause panic.
  1037  	testKit.MustInterDirc("drop stats t")
  1038  	h.UFIDelateStatsByLocalFeedback(s.do.SchemaReplicant())
  1039  }
  1040  
  1041  func (s *testStatsSuite) TestUFIDelatePartitionStatsByLocalFeedback(c *C) {
  1042  	defer cleanEnv(c, s.causetstore, s.do)
  1043  	testKit := testkit.NewTestKit(c, s.causetstore)
  1044  	testKit.MustInterDirc("use test")
  1045  	testKit.MustInterDirc(`set @@milevadb_partition_prune_mode='` + string(variable.StaticOnly) + `'`)
  1046  	testKit.MustInterDirc("create causet t (a bigint(64), b bigint(64), primary key(a)) partition by range (a) (partition p0 values less than (6))")
  1047  	testKit.MustInterDirc("insert into t values (1,2),(2,2),(4,5)")
  1048  	testKit.MustInterDirc("analyze causet t")
  1049  	testKit.MustInterDirc("insert into t values (3,5)")
  1050  	h := s.do.StatsHandle()
  1051  	oriProbability := statistics.FeedbackProbability
  1052  	oriMinLogCount := handle.MinLogScanCount
  1053  	oriErrorRate := handle.MinLogErrorRate
  1054  	defer func() {
  1055  		statistics.FeedbackProbability = oriProbability
  1056  		handle.MinLogScanCount = oriMinLogCount
  1057  		handle.MinLogErrorRate = oriErrorRate
  1058  	}()
  1059  	statistics.FeedbackProbability.CausetStore(1)
  1060  	handle.MinLogScanCount = 0
  1061  	handle.MinLogErrorRate = 0
  1062  
  1063  	is := s.do.SchemaReplicant()
  1064  	causet, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
  1065  	c.Assert(err, IsNil)
  1066  
  1067  	testKit.MustQuery("select * from t where a > 1")
  1068  
  1069  	h.UFIDelateStatsByLocalFeedback(s.do.SchemaReplicant())
  1070  
  1071  	tblInfo := causet.Meta()
  1072  	pid := tblInfo.Partition.Definitions[0].ID
  1073  	tbl := h.GetPartitionStats(tblInfo, pid)
  1074  
  1075  	c.Assert(tbl.DeferredCausets[tblInfo.DeferredCausets[0].ID].ToString(0), Equals, "column:1 ndv:3 totDefCausSize:0\n"+
  1076  		"num: 1 lower_bound: 1 upper_bound: 1 repeats: 1\n"+
  1077  		"num: 2 lower_bound: 2 upper_bound: 4 repeats: 0\n"+
  1078  		"num: 1 lower_bound: 4 upper_bound: 9223372036854775807 repeats: 0")
  1079  }
  1080  
  1081  type logHook struct {
  1082  	zapembedded.Core
  1083  	results string
  1084  }
  1085  
  1086  func (h *logHook) Write(entry zapembedded.Entry, fields []zapembedded.Field) error {
  1087  	message := entry.Message
  1088  	if idx := strings.Index(message, "[stats"); idx != -1 {
  1089  		h.results = h.results + message
  1090  		for _, f := range fields {
  1091  			h.results = h.results + ", " + f.Key + "=" + h.field2String(f)
  1092  		}
  1093  	}
  1094  	return nil
  1095  }
  1096  
  1097  func (h *logHook) field2String(field zapembedded.Field) string {
  1098  	switch field.Type {
  1099  	case zapembedded.StringType:
  1100  		return field.String
  1101  	case zapembedded.Int64Type, zapembedded.Int32Type, zapembedded.Uint32Type, zapembedded.Uint64Type:
  1102  		return fmt.Sprintf("%v", field.Integer)
  1103  	case zapembedded.Float64Type:
  1104  		return fmt.Sprintf("%v", math.Float64frombits(uint64(field.Integer)))
  1105  	case zapembedded.StringerType:
  1106  		return field.Interface.(fmt.Stringer).String()
  1107  	}
  1108  	return "not support"
  1109  }
  1110  
  1111  func (h *logHook) Check(e zapembedded.Entry, ce *zapembedded.CheckedEntry) *zapembedded.CheckedEntry {
  1112  	if h.Enabled(e.Level) {
  1113  		return ce.AddCore(e, h)
  1114  	}
  1115  	return ce
  1116  }
  1117  
  1118  func (s *testStatsSuite) TestLogDetailedInfo(c *C) {
  1119  	defer cleanEnv(c, s.causetstore, s.do)
  1120  
  1121  	oriProbability := statistics.FeedbackProbability
  1122  	oriMinLogCount := handle.MinLogScanCount
  1123  	oriMinError := handle.MinLogErrorRate
  1124  	oriLevel := log.GetLevel()
  1125  	oriLease := s.do.StatsHandle().Lease()
  1126  	defer func() {
  1127  		statistics.FeedbackProbability = oriProbability
  1128  		handle.MinLogScanCount = oriMinLogCount
  1129  		handle.MinLogErrorRate = oriMinError
  1130  		s.do.StatsHandle().SetLease(oriLease)
  1131  		log.SetLevel(oriLevel)
  1132  	}()
  1133  	statistics.FeedbackProbability.CausetStore(1)
  1134  	handle.MinLogScanCount = 0
  1135  	handle.MinLogErrorRate = 0
  1136  	s.do.StatsHandle().SetLease(1)
  1137  
  1138  	testKit := testkit.NewTestKit(c, s.causetstore)
  1139  	testKit.MustInterDirc("use test")
  1140  	testKit.MustInterDirc("create causet t (a bigint(64), b bigint(64), c bigint(64), primary key(a), index idx(b), index idx_ba(b,a), index idx_bc(b,c))")
  1141  	for i := 0; i < 20; i++ {
  1142  		testKit.MustInterDirc(fmt.Sprintf("insert into t values (%d, %d, %d)", i, i, i))
  1143  	}
  1144  	testKit.MustInterDirc("analyze causet t with 4 buckets")
  1145  	tests := []struct {
  1146  		allegrosql string
  1147  		result     string
  1148  	}{
  1149  		{
  1150  			allegrosql: "select * from t where t.a <= 15",
  1151  			result: "[stats-feedback] test.t, column=a, rangeStr=range: [-inf,8), actual: 8, expected: 8, buckets: {num: 8 lower_bound: 0 upper_bound: 7 repeats: 1, num: 8 lower_bound: 8 upper_bound: 15 repeats: 1}" +
  1152  				"[stats-feedback] test.t, column=a, rangeStr=range: [8,15), actual: 8, expected: 7, buckets: {num: 8 lower_bound: 8 upper_bound: 15 repeats: 1}",
  1153  		},
  1154  		{
  1155  			allegrosql: "select * from t use index(idx) where t.b <= 15",
  1156  			result: "[stats-feedback] test.t, index=idx, rangeStr=range: [-inf,8), actual: 8, expected: 8, histogram: {num: 8 lower_bound: 0 upper_bound: 7 repeats: 1, num: 8 lower_bound: 8 upper_bound: 15 repeats: 1}" +
  1157  				"[stats-feedback] test.t, index=idx, rangeStr=range: [8,16), actual: 8, expected: 8, histogram: {num: 8 lower_bound: 8 upper_bound: 15 repeats: 1, num: 4 lower_bound: 16 upper_bound: 19 repeats: 1}",
  1158  		},
  1159  		{
  1160  			allegrosql: "select b from t use index(idx_ba) where b = 1 and a <= 5",
  1161  			result:     "[stats-feedback] test.t, index=idx_ba, actual=1, equality=1, expected equality=1, range=range: [-inf,6], actual: -1, expected: 6, buckets: {num: 8 lower_bound: 0 upper_bound: 7 repeats: 1}",
  1162  		},
  1163  		{
  1164  			allegrosql: "select b from t use index(idx_bc) where b = 1 and c <= 5",
  1165  			result:     "[stats-feedback] test.t, index=idx_bc, actual=1, equality=1, expected equality=1, range=[-inf,6], pseudo count=7",
  1166  		},
  1167  		{
  1168  			allegrosql: "select b from t use index(idx_ba) where b = 1",
  1169  			result:     "[stats-feedback] test.t, index=idx_ba, rangeStr=value: 1, actual: 1, expected: 1",
  1170  		},
  1171  	}
  1172  	log.SetLevel(zapembedded.DebugLevel)
  1173  	for _, t := range tests {
  1174  		s.hook.results = ""
  1175  		testKit.MustQuery(t.allegrosql)
  1176  		c.Assert(s.hook.results, Equals, t.result)
  1177  	}
  1178  }
  1179  
  1180  func (s *testStatsSuite) TestNeedAnalyzeTable(c *C) {
  1181  	columns := map[int64]*statistics.DeferredCauset{}
  1182  	columns[1] = &statistics.DeferredCauset{Count: 1}
  1183  	tests := []struct {
  1184  		tbl    *statistics.Block
  1185  		ratio  float64
  1186  		limit  time.Duration
  1187  		start  string
  1188  		end    string
  1189  		now    string
  1190  		result bool
  1191  		reason string
  1192  	}{
  1193  		// causet was never analyzed and has reach the limit
  1194  		{
  1195  			tbl:    &statistics.Block{Version: oracle.EncodeTSO(oracle.GetPhysical(time.Now()))},
  1196  			limit:  0,
  1197  			ratio:  0,
  1198  			start:  "00:00 +0800",
  1199  			end:    "00:01 +0800",
  1200  			now:    "00:00 +0800",
  1201  			result: true,
  1202  			reason: "causet unanalyzed",
  1203  		},
  1204  		// causet was never analyzed but has not reach the limit
  1205  		{
  1206  			tbl:    &statistics.Block{Version: oracle.EncodeTSO(oracle.GetPhysical(time.Now()))},
  1207  			limit:  time.Hour,
  1208  			ratio:  0,
  1209  			start:  "00:00 +0800",
  1210  			end:    "00:01 +0800",
  1211  			now:    "00:00 +0800",
  1212  			result: false,
  1213  			reason: "",
  1214  		},
  1215  		// causet was already analyzed but auto analyze is disabled
  1216  		{
  1217  			tbl:    &statistics.Block{HistDefCausl: statistics.HistDefCausl{DeferredCausets: columns, ModifyCount: 1, Count: 1}},
  1218  			limit:  0,
  1219  			ratio:  0,
  1220  			start:  "00:00 +0800",
  1221  			end:    "00:01 +0800",
  1222  			now:    "00:00 +0800",
  1223  			result: false,
  1224  			reason: "",
  1225  		},
  1226  		// causet was already analyzed and but modify count is small
  1227  		{
  1228  			tbl:    &statistics.Block{HistDefCausl: statistics.HistDefCausl{DeferredCausets: columns, ModifyCount: 0, Count: 1}},
  1229  			limit:  0,
  1230  			ratio:  0.3,
  1231  			start:  "00:00 +0800",
  1232  			end:    "00:01 +0800",
  1233  			now:    "00:00 +0800",
  1234  			result: false,
  1235  			reason: "",
  1236  		},
  1237  		// causet was already analyzed and but not within time period
  1238  		{
  1239  			tbl:    &statistics.Block{HistDefCausl: statistics.HistDefCausl{DeferredCausets: columns, ModifyCount: 1, Count: 1}},
  1240  			limit:  0,
  1241  			ratio:  0.3,
  1242  			start:  "00:00 +0800",
  1243  			end:    "00:01 +0800",
  1244  			now:    "00:02 +0800",
  1245  			result: false,
  1246  			reason: "",
  1247  		},
  1248  		// causet was already analyzed and but not within time period
  1249  		{
  1250  			tbl:    &statistics.Block{HistDefCausl: statistics.HistDefCausl{DeferredCausets: columns, ModifyCount: 1, Count: 1}},
  1251  			limit:  0,
  1252  			ratio:  0.3,
  1253  			start:  "22:00 +0800",
  1254  			end:    "06:00 +0800",
  1255  			now:    "10:00 +0800",
  1256  			result: false,
  1257  			reason: "",
  1258  		},
  1259  		// causet was already analyzed and within time period
  1260  		{
  1261  			tbl:    &statistics.Block{HistDefCausl: statistics.HistDefCausl{DeferredCausets: columns, ModifyCount: 1, Count: 1}},
  1262  			limit:  0,
  1263  			ratio:  0.3,
  1264  			start:  "00:00 +0800",
  1265  			end:    "00:01 +0800",
  1266  			now:    "00:00 +0800",
  1267  			result: true,
  1268  			reason: "too many modifications",
  1269  		},
  1270  		// causet was already analyzed and within time period
  1271  		{
  1272  			tbl:    &statistics.Block{HistDefCausl: statistics.HistDefCausl{DeferredCausets: columns, ModifyCount: 1, Count: 1}},
  1273  			limit:  0,
  1274  			ratio:  0.3,
  1275  			start:  "22:00 +0800",
  1276  			end:    "06:00 +0800",
  1277  			now:    "23:00 +0800",
  1278  			result: true,
  1279  			reason: "too many modifications",
  1280  		},
  1281  	}
  1282  	for _, test := range tests {
  1283  		start, err := time.ParseInLocation(variable.FullDayTimeFormat, test.start, time.UTC)
  1284  		c.Assert(err, IsNil)
  1285  		end, err := time.ParseInLocation(variable.FullDayTimeFormat, test.end, time.UTC)
  1286  		c.Assert(err, IsNil)
  1287  		now, err := time.ParseInLocation(variable.FullDayTimeFormat, test.now, time.UTC)
  1288  		c.Assert(err, IsNil)
  1289  		needAnalyze, reason := handle.NeedAnalyzeTable(test.tbl, test.limit, test.ratio, start, end, now)
  1290  		c.Assert(needAnalyze, Equals, test.result)
  1291  		c.Assert(strings.HasPrefix(reason, test.reason), IsTrue)
  1292  	}
  1293  }
  1294  
  1295  func (s *testStatsSuite) TestIndexQueryFeedback(c *C) {
  1296  	c.Skip("support uFIDelate the topn of index equal conditions")
  1297  	defer cleanEnv(c, s.causetstore, s.do)
  1298  	testKit := testkit.NewTestKit(c, s.causetstore)
  1299  
  1300  	oriProbability := statistics.FeedbackProbability
  1301  	defer func() {
  1302  		statistics.FeedbackProbability = oriProbability
  1303  	}()
  1304  	statistics.FeedbackProbability.CausetStore(1)
  1305  
  1306  	testKit.MustInterDirc("use test")
  1307  	testKit.MustInterDirc("create causet t (a bigint(64), b bigint(64), c bigint(64), d float, e double, f decimal(17,2), " +
  1308  		"g time, h date, index idx_b(b), index idx_ab(a,b), index idx_ac(a,c), index idx_ad(a, d), index idx_ae(a, e), index idx_af(a, f)," +
  1309  		" index idx_ag(a, g), index idx_ah(a, h))")
  1310  	for i := 0; i < 20; i++ {
  1311  		testKit.MustInterDirc(fmt.Sprintf(`insert into t values (1, %d, %d, %d, %d, %d, %d, "%s")`, i, i, i, i, i, i, fmt.Sprintf("1000-01-%02d", i+1)))
  1312  	}
  1313  	h := s.do.StatsHandle()
  1314  	h.HandleDBSEvent(<-h.DBSEventCh())
  1315  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
  1316  	testKit.MustInterDirc("analyze causet t with 3 buckets")
  1317  	for i := 0; i < 20; i++ {
  1318  		testKit.MustInterDirc(fmt.Sprintf(`insert into t values (1, %d, %d, %d, %d, %d, %d, "%s")`, i, i, i, i, i, i, fmt.Sprintf("1000-01-%02d", i+1)))
  1319  	}
  1320  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
  1321  	is := s.do.SchemaReplicant()
  1322  	c.Assert(h.UFIDelate(is), IsNil)
  1323  	causet, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
  1324  	c.Assert(err, IsNil)
  1325  	tblInfo := causet.Meta()
  1326  	tests := []struct {
  1327  		allegrosql  string
  1328  		hist        string
  1329  		idxDefCauss int
  1330  		rangeID     int64
  1331  		idxID       int64
  1332  		eqCount     uint32
  1333  	}{
  1334  		{
  1335  			allegrosql: "select * from t use index(idx_ab) where a = 1 and b < 21",
  1336  			hist: "index:1 ndv:20\n" +
  1337  				"num: 16 lower_bound: -inf upper_bound: 7 repeats: 0\n" +
  1338  				"num: 16 lower_bound: 8 upper_bound: 15 repeats: 0\n" +
  1339  				"num: 9 lower_bound: 16 upper_bound: 21 repeats: 0",
  1340  			rangeID:     tblInfo.Indices[0].ID,
  1341  			idxID:       tblInfo.Indices[1].ID,
  1342  			idxDefCauss: 1,
  1343  			eqCount:     32,
  1344  		},
  1345  		{
  1346  			allegrosql: "select * from t use index(idx_ac) where a = 1 and c < 21",
  1347  			hist: "column:3 ndv:20 totDefCausSize:40\n" +
  1348  				"num: 13 lower_bound: -9223372036854775808 upper_bound: 6 repeats: 0\n" +
  1349  				"num: 13 lower_bound: 7 upper_bound: 13 repeats: 0\n" +
  1350  				"num: 12 lower_bound: 14 upper_bound: 21 repeats: 0",
  1351  			rangeID:     tblInfo.DeferredCausets[2].ID,
  1352  			idxID:       tblInfo.Indices[2].ID,
  1353  			idxDefCauss: 0,
  1354  			eqCount:     32,
  1355  		},
  1356  		{
  1357  			allegrosql: "select * from t use index(idx_ad) where a = 1 and d < 21",
  1358  			hist: "column:4 ndv:20 totDefCausSize:320\n" +
  1359  				"num: 13 lower_bound: -10000000000000 upper_bound: 6 repeats: 0\n" +
  1360  				"num: 12 lower_bound: 7 upper_bound: 13 repeats: 0\n" +
  1361  				"num: 10 lower_bound: 14 upper_bound: 21 repeats: 0",
  1362  			rangeID:     tblInfo.DeferredCausets[3].ID,
  1363  			idxID:       tblInfo.Indices[3].ID,
  1364  			idxDefCauss: 0,
  1365  			eqCount:     32,
  1366  		},
  1367  		{
  1368  			allegrosql: "select * from t use index(idx_ae) where a = 1 and e < 21",
  1369  			hist: "column:5 ndv:20 totDefCausSize:320\n" +
  1370  				"num: 13 lower_bound: -100000000000000000000000 upper_bound: 6 repeats: 0\n" +
  1371  				"num: 12 lower_bound: 7 upper_bound: 13 repeats: 0\n" +
  1372  				"num: 10 lower_bound: 14 upper_bound: 21 repeats: 0",
  1373  			rangeID:     tblInfo.DeferredCausets[4].ID,
  1374  			idxID:       tblInfo.Indices[4].ID,
  1375  			idxDefCauss: 0,
  1376  			eqCount:     32,
  1377  		},
  1378  		{
  1379  			allegrosql: "select * from t use index(idx_af) where a = 1 and f < 21",
  1380  			hist: "column:6 ndv:20 totDefCausSize:400\n" +
  1381  				"num: 13 lower_bound: -999999999999999.99 upper_bound: 6.00 repeats: 0\n" +
  1382  				"num: 12 lower_bound: 7.00 upper_bound: 13.00 repeats: 0\n" +
  1383  				"num: 10 lower_bound: 14.00 upper_bound: 21.00 repeats: 0",
  1384  			rangeID:     tblInfo.DeferredCausets[5].ID,
  1385  			idxID:       tblInfo.Indices[5].ID,
  1386  			idxDefCauss: 0,
  1387  			eqCount:     32,
  1388  		},
  1389  		{
  1390  			allegrosql: "select * from t use index(idx_ag) where a = 1 and g < 21",
  1391  			hist: "column:7 ndv:20 totDefCausSize:196\n" +
  1392  				"num: 13 lower_bound: -838:59:59 upper_bound: 00:00:06 repeats: 0\n" +
  1393  				"num: 12 lower_bound: 00:00:07 upper_bound: 00:00:13 repeats: 0\n" +
  1394  				"num: 10 lower_bound: 00:00:14 upper_bound: 00:00:21 repeats: 0",
  1395  			rangeID:     tblInfo.DeferredCausets[6].ID,
  1396  			idxID:       tblInfo.Indices[6].ID,
  1397  			idxDefCauss: 0,
  1398  			eqCount:     30,
  1399  		},
  1400  		{
  1401  			allegrosql: `select * from t use index(idx_ah) where a = 1 and h < "1000-01-21"`,
  1402  			hist: "column:8 ndv:20 totDefCausSize:360\n" +
  1403  				"num: 13 lower_bound: 1000-01-01 upper_bound: 1000-01-07 repeats: 0\n" +
  1404  				"num: 12 lower_bound: 1000-01-08 upper_bound: 1000-01-14 repeats: 0\n" +
  1405  				"num: 10 lower_bound: 1000-01-15 upper_bound: 1000-01-21 repeats: 0",
  1406  			rangeID:     tblInfo.DeferredCausets[7].ID,
  1407  			idxID:       tblInfo.Indices[7].ID,
  1408  			idxDefCauss: 0,
  1409  			eqCount:     32,
  1410  		},
  1411  	}
  1412  	for i, t := range tests {
  1413  		testKit.MustQuery(t.allegrosql)
  1414  		c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
  1415  		c.Assert(h.DumpStatsFeedbackToKV(), IsNil)
  1416  		c.Assert(h.HandleUFIDelateStats(s.do.SchemaReplicant()), IsNil)
  1417  		c.Assert(h.UFIDelate(is), IsNil)
  1418  		tbl := h.GetTableStats(tblInfo)
  1419  		if t.idxDefCauss == 0 {
  1420  			c.Assert(tbl.DeferredCausets[t.rangeID].ToString(0), Equals, tests[i].hist)
  1421  		} else {
  1422  			c.Assert(tbl.Indices[t.rangeID].ToString(1), Equals, tests[i].hist)
  1423  		}
  1424  		val, err := codec.EncodeKey(testKit.Se.GetStochastikVars().StmtCtx, nil, types.NewIntCauset(1))
  1425  		c.Assert(err, IsNil)
  1426  		c.Assert(tbl.Indices[t.idxID].CMSketch.QueryBytes(val), Equals, uint64(t.eqCount))
  1427  	}
  1428  }
  1429  
  1430  func (s *testStatsSuite) TestIndexQueryFeedback4TopN(c *C) {
  1431  	defer cleanEnv(c, s.causetstore, s.do)
  1432  	testKit := testkit.NewTestKit(c, s.causetstore)
  1433  
  1434  	oriProbability := statistics.FeedbackProbability
  1435  	oriMinLogCount := handle.MinLogScanCount
  1436  	oriErrorRate := handle.MinLogErrorRate
  1437  	defer func() {
  1438  		statistics.FeedbackProbability = oriProbability
  1439  		handle.MinLogScanCount = oriMinLogCount
  1440  		handle.MinLogErrorRate = oriErrorRate
  1441  	}()
  1442  	statistics.FeedbackProbability.CausetStore(1)
  1443  	handle.MinLogScanCount = 0
  1444  	handle.MinLogErrorRate = 0
  1445  
  1446  	testKit.MustInterDirc("use test")
  1447  	testKit.MustInterDirc("create causet t (a bigint(64), index idx(a))")
  1448  	for i := 0; i < 20; i++ {
  1449  		testKit.MustInterDirc(`insert into t values (1)`)
  1450  	}
  1451  	h := s.do.StatsHandle()
  1452  	h.HandleDBSEvent(<-h.DBSEventCh())
  1453  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
  1454  	testKit.MustInterDirc("set @@milevadb_enable_fast_analyze = 1")
  1455  	testKit.MustInterDirc("analyze causet t with 3 buckets")
  1456  	for i := 0; i < 20; i++ {
  1457  		testKit.MustInterDirc(`insert into t values (1)`)
  1458  	}
  1459  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
  1460  	is := s.do.SchemaReplicant()
  1461  	c.Assert(h.UFIDelate(is), IsNil)
  1462  	causet, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
  1463  	c.Assert(err, IsNil)
  1464  	tblInfo := causet.Meta()
  1465  
  1466  	testKit.MustQuery("select * from t use index(idx) where a = 1")
  1467  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
  1468  	c.Assert(h.DumpStatsFeedbackToKV(), IsNil)
  1469  	c.Assert(h.HandleUFIDelateStats(s.do.SchemaReplicant()), IsNil)
  1470  	c.Assert(h.UFIDelate(is), IsNil)
  1471  	tbl := h.GetTableStats(tblInfo)
  1472  	val, err := codec.EncodeKey(testKit.Se.GetStochastikVars().StmtCtx, nil, types.NewIntCauset(1))
  1473  	c.Assert(err, IsNil)
  1474  	c.Assert(tbl.Indices[1].CMSketch.QueryBytes(val), Equals, uint64(40))
  1475  }
  1476  
  1477  func (s *testStatsSuite) TestAbnormalIndexFeedback(c *C) {
  1478  	defer cleanEnv(c, s.causetstore, s.do)
  1479  	testKit := testkit.NewTestKit(c, s.causetstore)
  1480  
  1481  	oriProbability := statistics.FeedbackProbability
  1482  	oriMinLogCount := handle.MinLogScanCount
  1483  	oriErrorRate := handle.MinLogErrorRate
  1484  	defer func() {
  1485  		statistics.FeedbackProbability = oriProbability
  1486  		handle.MinLogScanCount = oriMinLogCount
  1487  		handle.MinLogErrorRate = oriErrorRate
  1488  	}()
  1489  	statistics.FeedbackProbability.CausetStore(1)
  1490  	handle.MinLogScanCount = 0
  1491  	handle.MinLogErrorRate = 0
  1492  
  1493  	testKit.MustInterDirc("use test")
  1494  	testKit.MustInterDirc("create causet t (a bigint(64), b bigint(64), index idx_ab(a,b))")
  1495  	for i := 0; i < 20; i++ {
  1496  		testKit.MustInterDirc(fmt.Sprintf("insert into t values (%d, %d)", i/5, i))
  1497  	}
  1498  	testKit.MustInterDirc("analyze causet t with 3 buckets")
  1499  	testKit.MustInterDirc("delete from t where a = 1")
  1500  	testKit.MustInterDirc("delete from t where b > 10")
  1501  	is := s.do.SchemaReplicant()
  1502  	causet, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
  1503  	c.Assert(err, IsNil)
  1504  	tblInfo := causet.Meta()
  1505  	h := s.do.StatsHandle()
  1506  	tests := []struct {
  1507  		allegrosql string
  1508  		hist       string
  1509  		rangeID    int64
  1510  		idxID      int64
  1511  		eqCount    uint32
  1512  	}{
  1513  		{
  1514  			// The real count of `a = 1` is 0.
  1515  			allegrosql: "select * from t where a = 1 and b < 21",
  1516  			hist: "column:2 ndv:20 totDefCausSize:20\n" +
  1517  				"num: 5 lower_bound: -9223372036854775808 upper_bound: 7 repeats: 0\n" +
  1518  				"num: 4 lower_bound: 7 upper_bound: 14 repeats: 0\n" +
  1519  				"num: 4 lower_bound: 14 upper_bound: 21 repeats: 0",
  1520  			rangeID: tblInfo.DeferredCausets[1].ID,
  1521  			idxID:   tblInfo.Indices[0].ID,
  1522  			eqCount: 3,
  1523  		},
  1524  		{
  1525  			// The real count of `b > 10` is 0.
  1526  			allegrosql: "select * from t where a = 2 and b > 10",
  1527  			hist: "column:2 ndv:20 totDefCausSize:20\n" +
  1528  				"num: 5 lower_bound: -9223372036854775808 upper_bound: 7 repeats: 0\n" +
  1529  				"num: 4 lower_bound: 7 upper_bound: 14 repeats: 0\n" +
  1530  				"num: 5 lower_bound: 14 upper_bound: 9223372036854775807 repeats: 0",
  1531  			rangeID: tblInfo.DeferredCausets[1].ID,
  1532  			idxID:   tblInfo.Indices[0].ID,
  1533  			eqCount: 3,
  1534  		},
  1535  	}
  1536  	for i, t := range tests {
  1537  		testKit.MustQuery(t.allegrosql)
  1538  		c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
  1539  		c.Assert(h.DumpStatsFeedbackToKV(), IsNil)
  1540  		c.Assert(h.HandleUFIDelateStats(s.do.SchemaReplicant()), IsNil)
  1541  		c.Assert(h.UFIDelate(is), IsNil)
  1542  		tbl := h.GetTableStats(tblInfo)
  1543  		c.Assert(tbl.DeferredCausets[t.rangeID].ToString(0), Equals, tests[i].hist)
  1544  		val, err := codec.EncodeKey(testKit.Se.GetStochastikVars().StmtCtx, nil, types.NewIntCauset(1))
  1545  		c.Assert(err, IsNil)
  1546  		c.Assert(tbl.Indices[t.idxID].CMSketch.QueryBytes(val), Equals, uint64(t.eqCount))
  1547  	}
  1548  }
  1549  
  1550  func (s *testStatsSuite) TestFeedbackRanges(c *C) {
  1551  	defer cleanEnv(c, s.causetstore, s.do)
  1552  	testKit := testkit.NewTestKit(c, s.causetstore)
  1553  	h := s.do.StatsHandle()
  1554  	oriProbability := statistics.FeedbackProbability
  1555  	oriNumber := statistics.MaxNumberOfRanges
  1556  	oriMinLogCount := handle.MinLogScanCount
  1557  	oriErrorRate := handle.MinLogErrorRate
  1558  	defer func() {
  1559  		statistics.FeedbackProbability = oriProbability
  1560  		statistics.MaxNumberOfRanges = oriNumber
  1561  		handle.MinLogScanCount = oriMinLogCount
  1562  		handle.MinLogErrorRate = oriErrorRate
  1563  	}()
  1564  	statistics.FeedbackProbability.CausetStore(1)
  1565  	handle.MinLogScanCount = 0
  1566  	handle.MinLogErrorRate = 0
  1567  
  1568  	testKit.MustInterDirc("use test")
  1569  	testKit.MustInterDirc("create causet t (a tinyint, b tinyint, primary key(a), index idx(a, b))")
  1570  	for i := 0; i < 20; i++ {
  1571  		testKit.MustInterDirc(fmt.Sprintf("insert into t values (%d, %d)", i, i))
  1572  	}
  1573  	h.HandleDBSEvent(<-h.DBSEventCh())
  1574  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
  1575  	testKit.MustInterDirc("analyze causet t with 3 buckets")
  1576  	for i := 30; i < 40; i++ {
  1577  		testKit.MustInterDirc(fmt.Sprintf("insert into t values (%d, %d)", i, i))
  1578  	}
  1579  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
  1580  	tests := []struct {
  1581  		allegrosql string
  1582  		hist       string
  1583  		colID      int64
  1584  	}{
  1585  		{
  1586  			allegrosql: "select * from t where a <= 50 or (a > 130 and a < 140)",
  1587  			hist: "column:1 ndv:30 totDefCausSize:0\n" +
  1588  				"num: 8 lower_bound: -128 upper_bound: 8 repeats: 0\n" +
  1589  				"num: 8 lower_bound: 8 upper_bound: 16 repeats: 0\n" +
  1590  				"num: 14 lower_bound: 16 upper_bound: 50 repeats: 0",
  1591  			colID: 1,
  1592  		},
  1593  		{
  1594  			allegrosql: "select * from t where a >= 10",
  1595  			hist: "column:1 ndv:30 totDefCausSize:0\n" +
  1596  				"num: 8 lower_bound: -128 upper_bound: 8 repeats: 0\n" +
  1597  				"num: 8 lower_bound: 8 upper_bound: 16 repeats: 0\n" +
  1598  				"num: 14 lower_bound: 16 upper_bound: 127 repeats: 0",
  1599  			colID: 1,
  1600  		},
  1601  		{
  1602  			allegrosql: "select * from t use index(idx) where a = 1 and (b <= 50 or (b > 130 and b < 140))",
  1603  			hist: "column:2 ndv:20 totDefCausSize:30\n" +
  1604  				"num: 8 lower_bound: -128 upper_bound: 7 repeats: 0\n" +
  1605  				"num: 8 lower_bound: 7 upper_bound: 14 repeats: 0\n" +
  1606  				"num: 7 lower_bound: 14 upper_bound: 51 repeats: 0",
  1607  			colID: 2,
  1608  		},
  1609  	}
  1610  	is := s.do.SchemaReplicant()
  1611  	causet, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
  1612  	for i, t := range tests {
  1613  		testKit.MustQuery(t.allegrosql)
  1614  		c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
  1615  		c.Assert(h.DumpStatsFeedbackToKV(), IsNil)
  1616  		c.Assert(h.HandleUFIDelateStats(s.do.SchemaReplicant()), IsNil)
  1617  		c.Assert(err, IsNil)
  1618  		c.Assert(h.UFIDelate(is), IsNil)
  1619  		tblInfo := causet.Meta()
  1620  		tbl := h.GetTableStats(tblInfo)
  1621  		c.Assert(tbl.DeferredCausets[t.colID].ToString(0), Equals, tests[i].hist)
  1622  	}
  1623  }
  1624  
  1625  func (s *testStatsSuite) TestUnsignedFeedbackRanges(c *C) {
  1626  	defer cleanEnv(c, s.causetstore, s.do)
  1627  	testKit := testkit.NewTestKit(c, s.causetstore)
  1628  	h := s.do.StatsHandle()
  1629  
  1630  	oriProbability := statistics.FeedbackProbability
  1631  	oriMinLogCount := handle.MinLogScanCount
  1632  	oriErrorRate := handle.MinLogErrorRate
  1633  	oriNumber := statistics.MaxNumberOfRanges
  1634  	defer func() {
  1635  		statistics.FeedbackProbability = oriProbability
  1636  		handle.MinLogScanCount = oriMinLogCount
  1637  		handle.MinLogErrorRate = oriErrorRate
  1638  		statistics.MaxNumberOfRanges = oriNumber
  1639  	}()
  1640  	statistics.FeedbackProbability.CausetStore(1)
  1641  	handle.MinLogScanCount = 0
  1642  	handle.MinLogErrorRate = 0
  1643  
  1644  	testKit.MustInterDirc("use test")
  1645  	testKit.MustInterDirc("create causet t (a tinyint unsigned, primary key(a))")
  1646  	testKit.MustInterDirc("create causet t1 (a bigint unsigned, primary key(a))")
  1647  	for i := 0; i < 20; i++ {
  1648  		testKit.MustInterDirc(fmt.Sprintf("insert into t values (%d)", i))
  1649  		testKit.MustInterDirc(fmt.Sprintf("insert into t1 values (%d)", i))
  1650  	}
  1651  	h.HandleDBSEvent(<-h.DBSEventCh())
  1652  	h.HandleDBSEvent(<-h.DBSEventCh())
  1653  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
  1654  	testKit.MustInterDirc("analyze causet t, t1 with 3 buckets")
  1655  	for i := 30; i < 40; i++ {
  1656  		testKit.MustInterDirc(fmt.Sprintf("insert into t values (%d)", i))
  1657  		testKit.MustInterDirc(fmt.Sprintf("insert into t1 values (%d)", i))
  1658  	}
  1659  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
  1660  	tests := []struct {
  1661  		allegrosql string
  1662  		hist       string
  1663  		tblName    string
  1664  	}{
  1665  		{
  1666  			allegrosql: "select * from t where a <= 50",
  1667  			hist: "column:1 ndv:30 totDefCausSize:10\n" +
  1668  				"num: 8 lower_bound: 0 upper_bound: 8 repeats: 0\n" +
  1669  				"num: 8 lower_bound: 8 upper_bound: 16 repeats: 0\n" +
  1670  				"num: 14 lower_bound: 16 upper_bound: 50 repeats: 0",
  1671  			tblName: "t",
  1672  		},
  1673  		{
  1674  			allegrosql: "select count(*) from t",
  1675  			hist: "column:1 ndv:30 totDefCausSize:10\n" +
  1676  				"num: 8 lower_bound: 0 upper_bound: 8 repeats: 0\n" +
  1677  				"num: 8 lower_bound: 8 upper_bound: 16 repeats: 0\n" +
  1678  				"num: 14 lower_bound: 16 upper_bound: 255 repeats: 0",
  1679  			tblName: "t",
  1680  		},
  1681  		{
  1682  			allegrosql: "select * from t1 where a <= 50",
  1683  			hist: "column:1 ndv:30 totDefCausSize:10\n" +
  1684  				"num: 8 lower_bound: 0 upper_bound: 8 repeats: 0\n" +
  1685  				"num: 8 lower_bound: 8 upper_bound: 16 repeats: 0\n" +
  1686  				"num: 14 lower_bound: 16 upper_bound: 50 repeats: 0",
  1687  			tblName: "t1",
  1688  		},
  1689  		{
  1690  			allegrosql: "select count(*) from t1",
  1691  			hist: "column:1 ndv:30 totDefCausSize:10\n" +
  1692  				"num: 8 lower_bound: 0 upper_bound: 8 repeats: 0\n" +
  1693  				"num: 8 lower_bound: 8 upper_bound: 16 repeats: 0\n" +
  1694  				"num: 14 lower_bound: 16 upper_bound: 18446744073709551615 repeats: 0",
  1695  			tblName: "t1",
  1696  		},
  1697  	}
  1698  	is := s.do.SchemaReplicant()
  1699  	c.Assert(h.UFIDelate(is), IsNil)
  1700  	for i, t := range tests {
  1701  		causet, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr(t.tblName))
  1702  		c.Assert(err, IsNil)
  1703  		testKit.MustQuery(t.allegrosql)
  1704  		c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
  1705  		c.Assert(h.DumpStatsFeedbackToKV(), IsNil)
  1706  		c.Assert(h.HandleUFIDelateStats(s.do.SchemaReplicant()), IsNil)
  1707  		c.Assert(err, IsNil)
  1708  		c.Assert(h.UFIDelate(is), IsNil)
  1709  		tblInfo := causet.Meta()
  1710  		tbl := h.GetTableStats(tblInfo)
  1711  		c.Assert(tbl.DeferredCausets[1].ToString(0), Equals, tests[i].hist)
  1712  	}
  1713  }
  1714  
  1715  func (s *testStatsSuite) TestLoadHistCorrelation(c *C) {
  1716  	defer cleanEnv(c, s.causetstore, s.do)
  1717  	testKit := testkit.NewTestKit(c, s.causetstore)
  1718  	h := s.do.StatsHandle()
  1719  	origLease := h.Lease()
  1720  	h.SetLease(time.Second)
  1721  	defer func() { h.SetLease(origLease) }()
  1722  	testKit.MustInterDirc("use test")
  1723  	testKit.MustInterDirc("create causet t(c int)")
  1724  	testKit.MustInterDirc("insert into t values(1),(2),(3),(4),(5)")
  1725  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
  1726  	testKit.MustInterDirc("analyze causet t")
  1727  	h.Clear()
  1728  	c.Assert(h.UFIDelate(s.do.SchemaReplicant()), IsNil)
  1729  	result := testKit.MustQuery("show stats_histograms where Table_name = 't'")
  1730  	c.Assert(len(result.Rows()), Equals, 0)
  1731  	testKit.MustInterDirc("explain select * from t where c = 1")
  1732  	c.Assert(h.LoadNeededHistograms(), IsNil)
  1733  	result = testKit.MustQuery("show stats_histograms where Table_name = 't'")
  1734  	c.Assert(len(result.Rows()), Equals, 1)
  1735  	c.Assert(result.Rows()[0][9], Equals, "1")
  1736  }
  1737  
  1738  func (s *testStatsSuite) TestDeleteUFIDelateFeedback(c *C) {
  1739  	defer cleanEnv(c, s.causetstore, s.do)
  1740  	testKit := testkit.NewTestKit(c, s.causetstore)
  1741  
  1742  	oriProbability := statistics.FeedbackProbability
  1743  	defer func() {
  1744  		statistics.FeedbackProbability = oriProbability
  1745  	}()
  1746  	statistics.FeedbackProbability.CausetStore(1)
  1747  
  1748  	h := s.do.StatsHandle()
  1749  	testKit.MustInterDirc("use test")
  1750  	testKit.MustInterDirc("create causet t (a bigint(64), b bigint(64), index idx_ab(a,b))")
  1751  	for i := 0; i < 20; i++ {
  1752  		testKit.MustInterDirc(fmt.Sprintf("insert into t values (%d, %d)", i/5, i))
  1753  	}
  1754  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
  1755  	testKit.MustInterDirc("analyze causet t with 3 buckets")
  1756  
  1757  	testKit.MustInterDirc("delete from t where a = 1")
  1758  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
  1759  	c.Assert(h.GetQueryFeedback().Size, Equals, 0)
  1760  	testKit.MustInterDirc("uFIDelate t set a = 6 where a = 2")
  1761  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
  1762  	c.Assert(h.GetQueryFeedback().Size, Equals, 0)
  1763  	testKit.MustInterDirc("explain analyze delete from t where a = 3")
  1764  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
  1765  	c.Assert(h.GetQueryFeedback().Size, Equals, 0)
  1766  }
  1767  
  1768  func (s *testStatsSuite) BenchmarkHandleAutoAnalyze(c *C) {
  1769  	defer cleanEnv(c, s.causetstore, s.do)
  1770  	testKit := testkit.NewTestKit(c, s.causetstore)
  1771  	testKit.MustInterDirc("use test")
  1772  	h := s.do.StatsHandle()
  1773  	is := s.do.SchemaReplicant()
  1774  	for i := 0; i < c.N; i++ {
  1775  		h.HandleAutoAnalyze(is)
  1776  	}
  1777  }