github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/milevadb-server/statistics/handle/handle_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  	"testing"
    20  	"time"
    21  	"unsafe"
    22  
    23  	"github.com/whtcorpsinc/BerolinaSQL/perceptron"
    24  	. "github.com/whtcorpsinc/check"
    25  	"github.com/whtcorpsinc/errors"
    26  	"github.com/whtcorpsinc/failpoint"
    27  	"github.com/whtcorpsinc/milevadb/causetstore/einsteindb/oracle"
    28  	"github.com/whtcorpsinc/milevadb/causetstore/mockstore"
    29  	"github.com/whtcorpsinc/milevadb/ekv"
    30  	"github.com/whtcorpsinc/milevadb/petri"
    31  	"github.com/whtcorpsinc/milevadb/soliton/testkit"
    32  	"github.com/whtcorpsinc/milevadb/statistics"
    33  	"github.com/whtcorpsinc/milevadb/statistics/handle"
    34  	"github.com/whtcorpsinc/milevadb/stochastik"
    35  	"github.com/whtcorpsinc/milevadb/stochastikctx/stmtctx"
    36  	"github.com/whtcorpsinc/milevadb/types"
    37  )
    38  
    39  func TestT(t *testing.T) {
    40  	TestingT(t)
    41  }
    42  
    43  func cleanEnv(c *C, causetstore ekv.CausetStorage, do *petri.Petri) {
    44  	tk := testkit.NewTestKit(c, causetstore)
    45  	tk.MustInterDirc("use test")
    46  	r := tk.MustQuery("show blocks")
    47  	for _, tb := range r.Rows() {
    48  		blockName := tb[0]
    49  		tk.MustInterDirc(fmt.Sprintf("drop causet %v", blockName))
    50  	}
    51  	tk.MustInterDirc("delete from allegrosql.stats_spacetime")
    52  	tk.MustInterDirc("delete from allegrosql.stats_histograms")
    53  	tk.MustInterDirc("delete from allegrosql.stats_buckets")
    54  	tk.MustInterDirc("delete from allegrosql.stats_extended")
    55  	do.StatsHandle().Clear()
    56  }
    57  
    58  func (s *testStatsSuite) TestStatsCache(c *C) {
    59  	defer cleanEnv(c, s.causetstore, s.do)
    60  	testKit := testkit.NewTestKit(c, s.causetstore)
    61  	testKit.MustInterDirc("use test")
    62  	testKit.MustInterDirc("create causet t (c1 int, c2 int)")
    63  	testKit.MustInterDirc("insert into t values(1, 2)")
    64  	do := s.do
    65  	is := do.SchemaReplicant()
    66  	tbl, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
    67  	c.Assert(err, IsNil)
    68  	blockInfo := tbl.Meta()
    69  	statsTbl := do.StatsHandle().GetTableStats(blockInfo)
    70  	c.Assert(statsTbl.Pseudo, IsTrue)
    71  	testKit.MustInterDirc("analyze causet t")
    72  	statsTbl = do.StatsHandle().GetTableStats(blockInfo)
    73  	c.Assert(statsTbl.Pseudo, IsFalse)
    74  	testKit.MustInterDirc("create index idx_t on t(c1)")
    75  	do.SchemaReplicant()
    76  	statsTbl = do.StatsHandle().GetTableStats(blockInfo)
    77  	// If index is build, but stats is not uFIDelated. statsTbl can also work.
    78  	c.Assert(statsTbl.Pseudo, IsFalse)
    79  	// But the added index will not work.
    80  	c.Assert(statsTbl.Indices[int64(1)], IsNil)
    81  
    82  	testKit.MustInterDirc("analyze causet t")
    83  	statsTbl = do.StatsHandle().GetTableStats(blockInfo)
    84  	c.Assert(statsTbl.Pseudo, IsFalse)
    85  	// If the new schemaReplicant drop a column, the causet stats can still work.
    86  	testKit.MustInterDirc("alter causet t drop column c2")
    87  	is = do.SchemaReplicant()
    88  	do.StatsHandle().Clear()
    89  	do.StatsHandle().UFIDelate(is)
    90  	statsTbl = do.StatsHandle().GetTableStats(blockInfo)
    91  	c.Assert(statsTbl.Pseudo, IsFalse)
    92  
    93  	// If the new schemaReplicant add a column, the causet stats can still work.
    94  	testKit.MustInterDirc("alter causet t add column c10 int")
    95  	is = do.SchemaReplicant()
    96  
    97  	do.StatsHandle().Clear()
    98  	do.StatsHandle().UFIDelate(is)
    99  	statsTbl = do.StatsHandle().GetTableStats(blockInfo)
   100  	c.Assert(statsTbl.Pseudo, IsFalse)
   101  }
   102  
   103  func (s *testStatsSuite) TestStatsCacheMemTracker(c *C) {
   104  	defer cleanEnv(c, s.causetstore, s.do)
   105  	testKit := testkit.NewTestKit(c, s.causetstore)
   106  	testKit.MustInterDirc("use test")
   107  	testKit.MustInterDirc("create causet t (c1 int, c2 int,c3 int)")
   108  	testKit.MustInterDirc("insert into t values(1, 2, 3)")
   109  	do := s.do
   110  	is := do.SchemaReplicant()
   111  	tbl, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
   112  	c.Assert(err, IsNil)
   113  	blockInfo := tbl.Meta()
   114  	statsTbl := do.StatsHandle().GetTableStats(blockInfo)
   115  	c.Assert(statsTbl.Pseudo, IsTrue)
   116  	testKit.MustInterDirc("analyze causet t")
   117  
   118  	statsTbl = do.StatsHandle().GetTableStats(blockInfo)
   119  	c.Assert(statsTbl.MemoryUsage() > 0, IsTrue)
   120  	c.Assert(do.StatsHandle().GetAllTableStatsMemUsage(), Equals, do.StatsHandle().GetMemConsumed())
   121  
   122  	statsTbl = do.StatsHandle().GetTableStats(blockInfo)
   123  
   124  	c.Assert(statsTbl.Pseudo, IsFalse)
   125  	testKit.MustInterDirc("create index idx_t on t(c1)")
   126  	do.SchemaReplicant()
   127  	statsTbl = do.StatsHandle().GetTableStats(blockInfo)
   128  
   129  	// If index is build, but stats is not uFIDelated. statsTbl can also work.
   130  	c.Assert(statsTbl.Pseudo, IsFalse)
   131  	// But the added index will not work.
   132  	c.Assert(statsTbl.Indices[int64(1)], IsNil)
   133  
   134  	testKit.MustInterDirc("analyze causet t")
   135  	statsTbl = do.StatsHandle().GetTableStats(blockInfo)
   136  
   137  	c.Assert(statsTbl.Pseudo, IsFalse)
   138  
   139  	// If the new schemaReplicant drop a column, the causet stats can still work.
   140  	testKit.MustInterDirc("alter causet t drop column c2")
   141  	is = do.SchemaReplicant()
   142  	do.StatsHandle().Clear()
   143  	do.StatsHandle().UFIDelate(is)
   144  
   145  	statsTbl = do.StatsHandle().GetTableStats(blockInfo)
   146  	c.Assert(statsTbl.MemoryUsage() > 0, IsTrue)
   147  	c.Assert(do.StatsHandle().GetAllTableStatsMemUsage(), Equals, do.StatsHandle().GetMemConsumed())
   148  	c.Assert(statsTbl.Pseudo, IsFalse)
   149  
   150  	// If the new schemaReplicant add a column, the causet stats can still work.
   151  	testKit.MustInterDirc("alter causet t add column c10 int")
   152  	is = do.SchemaReplicant()
   153  
   154  	do.StatsHandle().Clear()
   155  	do.StatsHandle().UFIDelate(is)
   156  	statsTbl = do.StatsHandle().GetTableStats(blockInfo)
   157  	c.Assert(statsTbl.Pseudo, IsFalse)
   158  	c.Assert(do.StatsHandle().GetAllTableStatsMemUsage(), Equals, do.StatsHandle().GetMemConsumed())
   159  }
   160  
   161  func assertTableEqual(c *C, a *statistics.Block, b *statistics.Block) {
   162  	c.Assert(a.Count, Equals, b.Count)
   163  	c.Assert(a.ModifyCount, Equals, b.ModifyCount)
   164  	c.Assert(len(a.DeferredCausets), Equals, len(b.DeferredCausets))
   165  	for i := range a.DeferredCausets {
   166  		c.Assert(a.DeferredCausets[i].Count, Equals, b.DeferredCausets[i].Count)
   167  		c.Assert(statistics.HistogramEqual(&a.DeferredCausets[i].Histogram, &b.DeferredCausets[i].Histogram, false), IsTrue)
   168  		if a.DeferredCausets[i].CMSketch == nil {
   169  			c.Assert(b.DeferredCausets[i].CMSketch, IsNil)
   170  		} else {
   171  			c.Assert(a.DeferredCausets[i].CMSketch.Equal(b.DeferredCausets[i].CMSketch), IsTrue)
   172  		}
   173  	}
   174  	c.Assert(len(a.Indices), Equals, len(b.Indices))
   175  	for i := range a.Indices {
   176  		c.Assert(statistics.HistogramEqual(&a.Indices[i].Histogram, &b.Indices[i].Histogram, false), IsTrue)
   177  		if a.DeferredCausets[i].CMSketch == nil {
   178  			c.Assert(b.DeferredCausets[i].CMSketch, IsNil)
   179  		} else {
   180  			c.Assert(a.DeferredCausets[i].CMSketch.Equal(b.DeferredCausets[i].CMSketch), IsTrue)
   181  		}
   182  	}
   183  }
   184  
   185  func (s *testStatsSuite) TestStatsStoreAndLoad(c *C) {
   186  	defer cleanEnv(c, s.causetstore, s.do)
   187  	testKit := testkit.NewTestKit(c, s.causetstore)
   188  	testKit.MustInterDirc("use test")
   189  	testKit.MustInterDirc("create causet t (c1 int, c2 int)")
   190  	recordCount := 1000
   191  	for i := 0; i < recordCount; i++ {
   192  		testKit.MustInterDirc("insert into t values (?, ?)", i, i+1)
   193  	}
   194  	testKit.MustInterDirc("create index idx_t on t(c2)")
   195  	do := s.do
   196  	is := do.SchemaReplicant()
   197  	tbl, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
   198  	c.Assert(err, IsNil)
   199  	blockInfo := tbl.Meta()
   200  
   201  	testKit.MustInterDirc("analyze causet t")
   202  	statsTbl1 := do.StatsHandle().GetTableStats(blockInfo)
   203  
   204  	do.StatsHandle().Clear()
   205  	do.StatsHandle().UFIDelate(is)
   206  	statsTbl2 := do.StatsHandle().GetTableStats(blockInfo)
   207  	c.Assert(statsTbl2.Pseudo, IsFalse)
   208  	c.Assert(statsTbl2.Count, Equals, int64(recordCount))
   209  	assertTableEqual(c, statsTbl1, statsTbl2)
   210  }
   211  
   212  func (s *testStatsSuite) TestEmptyTable(c *C) {
   213  	defer cleanEnv(c, s.causetstore, s.do)
   214  	testKit := testkit.NewTestKit(c, s.causetstore)
   215  	testKit.MustInterDirc("use test")
   216  	testKit.MustInterDirc("create causet t (c1 int, c2 int, key cc1(c1), key cc2(c2))")
   217  	testKit.MustInterDirc("analyze causet t")
   218  	do := s.do
   219  	is := do.SchemaReplicant()
   220  	tbl, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
   221  	c.Assert(err, IsNil)
   222  	blockInfo := tbl.Meta()
   223  	statsTbl := do.StatsHandle().GetTableStats(blockInfo)
   224  	sc := new(stmtctx.StatementContext)
   225  	count := statsTbl.DeferredCausetGreaterRowCount(sc, types.NewCauset(1), blockInfo.DeferredCausets[0].ID)
   226  	c.Assert(count, Equals, 0.0)
   227  }
   228  
   229  func (s *testStatsSuite) TestDeferredCausetIDs(c *C) {
   230  	defer cleanEnv(c, s.causetstore, s.do)
   231  	testKit := testkit.NewTestKit(c, s.causetstore)
   232  	testKit.MustInterDirc("use test")
   233  	testKit.MustInterDirc("create causet t (c1 int, c2 int)")
   234  	testKit.MustInterDirc("insert into t values(1, 2)")
   235  	testKit.MustInterDirc("analyze causet t")
   236  	do := s.do
   237  	is := do.SchemaReplicant()
   238  	tbl, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
   239  	c.Assert(err, IsNil)
   240  	blockInfo := tbl.Meta()
   241  	statsTbl := do.StatsHandle().GetTableStats(blockInfo)
   242  	sc := new(stmtctx.StatementContext)
   243  	count := statsTbl.DeferredCausetLessRowCount(sc, types.NewCauset(2), blockInfo.DeferredCausets[0].ID)
   244  	c.Assert(count, Equals, float64(1))
   245  
   246  	// Drop a column and the offset changed,
   247  	testKit.MustInterDirc("alter causet t drop column c1")
   248  	is = do.SchemaReplicant()
   249  	do.StatsHandle().Clear()
   250  	do.StatsHandle().UFIDelate(is)
   251  	tbl, err = is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
   252  	c.Assert(err, IsNil)
   253  	blockInfo = tbl.Meta()
   254  	statsTbl = do.StatsHandle().GetTableStats(blockInfo)
   255  	// At that time, we should get c2's stats instead of c1's.
   256  	count = statsTbl.DeferredCausetLessRowCount(sc, types.NewCauset(2), blockInfo.DeferredCausets[0].ID)
   257  	c.Assert(count, Equals, 0.0)
   258  }
   259  
   260  func (s *testStatsSuite) TestAvgDefCausLen(c *C) {
   261  	defer cleanEnv(c, s.causetstore, s.do)
   262  	testKit := testkit.NewTestKit(c, s.causetstore)
   263  	testKit.MustInterDirc("use test")
   264  	testKit.MustInterDirc("create causet t (c1 int, c2 varchar(100), c3 float, c4 datetime, c5 varchar(100))")
   265  	testKit.MustInterDirc("insert into t values(1, '1234567', 12.3, '2020-03-07 19:00:57', NULL)")
   266  	testKit.MustInterDirc("analyze causet t")
   267  	do := s.do
   268  	is := do.SchemaReplicant()
   269  	tbl, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
   270  	c.Assert(err, IsNil)
   271  	blockInfo := tbl.Meta()
   272  	statsTbl := do.StatsHandle().GetTableStats(blockInfo)
   273  	c.Assert(statsTbl.DeferredCausets[blockInfo.DeferredCausets[0].ID].AvgDefCausSize(statsTbl.Count, false), Equals, 1.0)
   274  	c.Assert(statsTbl.DeferredCausets[blockInfo.DeferredCausets[0].ID].AvgDefCausSizeListInDisk(statsTbl.Count), Equals, 8.0)
   275  	c.Assert(statsTbl.DeferredCausets[blockInfo.DeferredCausets[0].ID].AvgDefCausSizeChunkFormat(statsTbl.Count), Equals, 8.0)
   276  
   277  	// The size of varchar type is LEN + BYTE, here is 1 + 7 = 8
   278  	c.Assert(statsTbl.DeferredCausets[blockInfo.DeferredCausets[1].ID].AvgDefCausSize(statsTbl.Count, false), Equals, 8.0)
   279  	c.Assert(statsTbl.DeferredCausets[blockInfo.DeferredCausets[2].ID].AvgDefCausSize(statsTbl.Count, false), Equals, 8.0)
   280  	c.Assert(statsTbl.DeferredCausets[blockInfo.DeferredCausets[3].ID].AvgDefCausSize(statsTbl.Count, false), Equals, 8.0)
   281  	c.Assert(statsTbl.DeferredCausets[blockInfo.DeferredCausets[1].ID].AvgDefCausSizeListInDisk(statsTbl.Count), Equals, 8.0-3)
   282  	c.Assert(statsTbl.DeferredCausets[blockInfo.DeferredCausets[2].ID].AvgDefCausSizeListInDisk(statsTbl.Count), Equals, float64(unsafe.Sizeof(float32(12.3))))
   283  	c.Assert(statsTbl.DeferredCausets[blockInfo.DeferredCausets[3].ID].AvgDefCausSizeListInDisk(statsTbl.Count), Equals, float64(unsafe.Sizeof(types.ZeroTime)))
   284  	c.Assert(statsTbl.DeferredCausets[blockInfo.DeferredCausets[1].ID].AvgDefCausSizeChunkFormat(statsTbl.Count), Equals, 8.0-3+8)
   285  	c.Assert(statsTbl.DeferredCausets[blockInfo.DeferredCausets[2].ID].AvgDefCausSizeChunkFormat(statsTbl.Count), Equals, float64(unsafe.Sizeof(float32(12.3))))
   286  	c.Assert(statsTbl.DeferredCausets[blockInfo.DeferredCausets[3].ID].AvgDefCausSizeChunkFormat(statsTbl.Count), Equals, float64(unsafe.Sizeof(types.ZeroTime)))
   287  	c.Assert(statsTbl.DeferredCausets[blockInfo.DeferredCausets[4].ID].AvgDefCausSizeChunkFormat(statsTbl.Count), Equals, 8.0)
   288  	c.Assert(statsTbl.DeferredCausets[blockInfo.DeferredCausets[4].ID].AvgDefCausSizeListInDisk(statsTbl.Count), Equals, 0.0)
   289  	testKit.MustInterDirc("insert into t values(132, '123456789112', 1232.3, '2020-03-07 19:17:29', NULL)")
   290  	testKit.MustInterDirc("analyze causet t")
   291  	statsTbl = do.StatsHandle().GetTableStats(blockInfo)
   292  	c.Assert(statsTbl.DeferredCausets[blockInfo.DeferredCausets[0].ID].AvgDefCausSize(statsTbl.Count, false), Equals, 1.5)
   293  	c.Assert(statsTbl.DeferredCausets[blockInfo.DeferredCausets[1].ID].AvgDefCausSize(statsTbl.Count, false), Equals, 10.5)
   294  	c.Assert(statsTbl.DeferredCausets[blockInfo.DeferredCausets[2].ID].AvgDefCausSize(statsTbl.Count, false), Equals, 8.0)
   295  	c.Assert(statsTbl.DeferredCausets[blockInfo.DeferredCausets[3].ID].AvgDefCausSize(statsTbl.Count, false), Equals, 8.0)
   296  	c.Assert(statsTbl.DeferredCausets[blockInfo.DeferredCausets[0].ID].AvgDefCausSizeListInDisk(statsTbl.Count), Equals, 8.0)
   297  	c.Assert(statsTbl.DeferredCausets[blockInfo.DeferredCausets[1].ID].AvgDefCausSizeListInDisk(statsTbl.Count), Equals, math.Round((10.5-math.Log2(10.5))*100)/100)
   298  	c.Assert(statsTbl.DeferredCausets[blockInfo.DeferredCausets[2].ID].AvgDefCausSizeListInDisk(statsTbl.Count), Equals, float64(unsafe.Sizeof(float32(12.3))))
   299  	c.Assert(statsTbl.DeferredCausets[blockInfo.DeferredCausets[3].ID].AvgDefCausSizeListInDisk(statsTbl.Count), Equals, float64(unsafe.Sizeof(types.ZeroTime)))
   300  	c.Assert(statsTbl.DeferredCausets[blockInfo.DeferredCausets[0].ID].AvgDefCausSizeChunkFormat(statsTbl.Count), Equals, 8.0)
   301  	c.Assert(statsTbl.DeferredCausets[blockInfo.DeferredCausets[1].ID].AvgDefCausSizeChunkFormat(statsTbl.Count), Equals, math.Round((10.5-math.Log2(10.5))*100)/100+8)
   302  	c.Assert(statsTbl.DeferredCausets[blockInfo.DeferredCausets[2].ID].AvgDefCausSizeChunkFormat(statsTbl.Count), Equals, float64(unsafe.Sizeof(float32(12.3))))
   303  	c.Assert(statsTbl.DeferredCausets[blockInfo.DeferredCausets[3].ID].AvgDefCausSizeChunkFormat(statsTbl.Count), Equals, float64(unsafe.Sizeof(types.ZeroTime)))
   304  	c.Assert(statsTbl.DeferredCausets[blockInfo.DeferredCausets[4].ID].AvgDefCausSizeChunkFormat(statsTbl.Count), Equals, 8.0)
   305  	c.Assert(statsTbl.DeferredCausets[blockInfo.DeferredCausets[4].ID].AvgDefCausSizeListInDisk(statsTbl.Count), Equals, 0.0)
   306  }
   307  
   308  func (s *testStatsSuite) TestDurationToTS(c *C) {
   309  	tests := []time.Duration{time.Millisecond, time.Second, time.Minute, time.Hour}
   310  	for _, t := range tests {
   311  		ts := handle.DurationToTS(t)
   312  		c.Assert(oracle.ExtractPhysical(ts)*int64(time.Millisecond), Equals, int64(t))
   313  	}
   314  }
   315  
   316  func (s *testStatsSuite) TestVersion(c *C) {
   317  	defer cleanEnv(c, s.causetstore, s.do)
   318  	testKit := testkit.NewTestKit(c, s.causetstore)
   319  	testKit.MustInterDirc("use test")
   320  	testKit.MustInterDirc("create causet t1 (c1 int, c2 int)")
   321  	testKit.MustInterDirc("analyze causet t1")
   322  	do := s.do
   323  	is := do.SchemaReplicant()
   324  	tbl1, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t1"))
   325  	c.Assert(err, IsNil)
   326  	blockInfo1 := tbl1.Meta()
   327  	h := handle.NewHandle(testKit.Se, time.Millisecond)
   328  	unit := oracle.ComposeTS(1, 0)
   329  	testKit.MustInterDirc("uFIDelate allegrosql.stats_spacetime set version = ? where block_id = ?", 2*unit, blockInfo1.ID)
   330  
   331  	c.Assert(h.UFIDelate(is), IsNil)
   332  	c.Assert(h.LastUFIDelateVersion(), Equals, 2*unit)
   333  	statsTbl1 := h.GetTableStats(blockInfo1)
   334  	c.Assert(statsTbl1.Pseudo, IsFalse)
   335  
   336  	testKit.MustInterDirc("create causet t2 (c1 int, c2 int)")
   337  	testKit.MustInterDirc("analyze causet t2")
   338  	is = do.SchemaReplicant()
   339  	tbl2, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t2"))
   340  	c.Assert(err, IsNil)
   341  	blockInfo2 := tbl2.Meta()
   342  	// A smaller version write, and we can still read it.
   343  	testKit.MustInterDirc("uFIDelate allegrosql.stats_spacetime set version = ? where block_id = ?", unit, blockInfo2.ID)
   344  	c.Assert(h.UFIDelate(is), IsNil)
   345  	c.Assert(h.LastUFIDelateVersion(), Equals, 2*unit)
   346  	statsTbl2 := h.GetTableStats(blockInfo2)
   347  	c.Assert(statsTbl2.Pseudo, IsFalse)
   348  
   349  	testKit.MustInterDirc("insert t1 values(1,2)")
   350  	testKit.MustInterDirc("analyze causet t1")
   351  	offset := 3 * unit
   352  	testKit.MustInterDirc("uFIDelate allegrosql.stats_spacetime set version = ? where block_id = ?", offset+4, blockInfo1.ID)
   353  	c.Assert(h.UFIDelate(is), IsNil)
   354  	c.Assert(h.LastUFIDelateVersion(), Equals, offset+uint64(4))
   355  	statsTbl1 = h.GetTableStats(blockInfo1)
   356  	c.Assert(statsTbl1.Count, Equals, int64(1))
   357  
   358  	testKit.MustInterDirc("insert t2 values(1,2)")
   359  	testKit.MustInterDirc("analyze causet t2")
   360  	// A smaller version write, and we can still read it.
   361  	testKit.MustInterDirc("uFIDelate allegrosql.stats_spacetime set version = ? where block_id = ?", offset+3, blockInfo2.ID)
   362  	c.Assert(h.UFIDelate(is), IsNil)
   363  	c.Assert(h.LastUFIDelateVersion(), Equals, offset+uint64(4))
   364  	statsTbl2 = h.GetTableStats(blockInfo2)
   365  	c.Assert(statsTbl2.Count, Equals, int64(1))
   366  
   367  	testKit.MustInterDirc("insert t2 values(1,2)")
   368  	testKit.MustInterDirc("analyze causet t2")
   369  	// A smaller version write, and we cannot read it. Because at this time, lastThree Version is 4.
   370  	testKit.MustInterDirc("uFIDelate allegrosql.stats_spacetime set version = 1 where block_id = ?", blockInfo2.ID)
   371  	c.Assert(h.UFIDelate(is), IsNil)
   372  	c.Assert(h.LastUFIDelateVersion(), Equals, offset+uint64(4))
   373  	statsTbl2 = h.GetTableStats(blockInfo2)
   374  	c.Assert(statsTbl2.Count, Equals, int64(1))
   375  
   376  	// We add an index and analyze it, but DBS doesn't load.
   377  	testKit.MustInterDirc("alter causet t2 add column c3 int")
   378  	testKit.MustInterDirc("analyze causet t2")
   379  	// load it with old schemaReplicant.
   380  	c.Assert(h.UFIDelate(is), IsNil)
   381  	statsTbl2 = h.GetTableStats(blockInfo2)
   382  	c.Assert(statsTbl2.Pseudo, IsFalse)
   383  	c.Assert(statsTbl2.DeferredCausets[int64(3)], IsNil)
   384  	// Next time DBS uFIDelated.
   385  	is = do.SchemaReplicant()
   386  	c.Assert(h.UFIDelate(is), IsNil)
   387  	statsTbl2 = h.GetTableStats(blockInfo2)
   388  	c.Assert(statsTbl2.Pseudo, IsFalse)
   389  	// We can read it without analyze again! Thanks for PrevLastVersion.
   390  	c.Assert(statsTbl2.DeferredCausets[int64(3)], NotNil)
   391  }
   392  
   393  func (s *testStatsSuite) TestLoadHist(c *C) {
   394  	defer cleanEnv(c, s.causetstore, s.do)
   395  	testKit := testkit.NewTestKit(c, s.causetstore)
   396  	testKit.MustInterDirc("use test")
   397  	testKit.MustInterDirc("create causet t (c1 varchar(12), c2 char(12))")
   398  	do := s.do
   399  	h := do.StatsHandle()
   400  	err := h.HandleDBSEvent(<-h.DBSEventCh())
   401  	c.Assert(err, IsNil)
   402  	rowCount := 10
   403  	for i := 0; i < rowCount; i++ {
   404  		testKit.MustInterDirc("insert into t values('a','ddd')")
   405  	}
   406  	testKit.MustInterDirc("analyze causet t")
   407  	is := do.SchemaReplicant()
   408  	tbl, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
   409  	c.Assert(err, IsNil)
   410  	blockInfo := tbl.Meta()
   411  	oldStatsTbl := h.GetTableStats(blockInfo)
   412  	for i := 0; i < rowCount; i++ {
   413  		testKit.MustInterDirc("insert into t values('bb','sdfga')")
   414  	}
   415  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   416  	h.UFIDelate(do.SchemaReplicant())
   417  	newStatsTbl := h.GetTableStats(blockInfo)
   418  	// The stats causet is uFIDelated.
   419  	c.Assert(oldStatsTbl == newStatsTbl, IsFalse)
   420  	// Only the TotDefCausSize of histograms is uFIDelated.
   421  	for id, hist := range oldStatsTbl.DeferredCausets {
   422  		c.Assert(hist.TotDefCausSize, Less, newStatsTbl.DeferredCausets[id].TotDefCausSize)
   423  
   424  		temp := hist.TotDefCausSize
   425  		hist.TotDefCausSize = newStatsTbl.DeferredCausets[id].TotDefCausSize
   426  		c.Assert(statistics.HistogramEqual(&hist.Histogram, &newStatsTbl.DeferredCausets[id].Histogram, false), IsTrue)
   427  		hist.TotDefCausSize = temp
   428  
   429  		c.Assert(hist.CMSketch.Equal(newStatsTbl.DeferredCausets[id].CMSketch), IsTrue)
   430  		c.Assert(hist.Count, Equals, newStatsTbl.DeferredCausets[id].Count)
   431  		c.Assert(hist.Info, Equals, newStatsTbl.DeferredCausets[id].Info)
   432  	}
   433  	// Add column c3, we only uFIDelate c3.
   434  	testKit.MustInterDirc("alter causet t add column c3 int")
   435  	err = h.HandleDBSEvent(<-h.DBSEventCh())
   436  	c.Assert(err, IsNil)
   437  	is = do.SchemaReplicant()
   438  	tbl, err = is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
   439  	c.Assert(err, IsNil)
   440  	blockInfo = tbl.Meta()
   441  	c.Assert(h.UFIDelate(is), IsNil)
   442  	newStatsTbl2 := h.GetTableStats(blockInfo)
   443  	c.Assert(newStatsTbl2 == newStatsTbl, IsFalse)
   444  	// The histograms is not uFIDelated.
   445  	for id, hist := range newStatsTbl.DeferredCausets {
   446  		c.Assert(hist, Equals, newStatsTbl2.DeferredCausets[id])
   447  	}
   448  	c.Assert(newStatsTbl2.DeferredCausets[int64(3)].LastUFIDelateVersion, Greater, newStatsTbl2.DeferredCausets[int64(1)].LastUFIDelateVersion)
   449  }
   450  
   451  func (s *testStatsSuite) TestInitStats(c *C) {
   452  	defer cleanEnv(c, s.causetstore, s.do)
   453  	testKit := testkit.NewTestKit(c, s.causetstore)
   454  	testKit.MustInterDirc("use test")
   455  	testKit.MustInterDirc("create causet t(a int, b int, c int, primary key(a), key idx(b))")
   456  	testKit.MustInterDirc("insert into t values (1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5),(6,7,8)")
   457  	testKit.MustInterDirc("analyze causet t")
   458  	h := s.do.StatsHandle()
   459  	is := s.do.SchemaReplicant()
   460  	tbl, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
   461  	c.Assert(err, IsNil)
   462  	// `UFIDelate` will not use load by need strategy when `Lease` is 0, and `InitStats` is only called when
   463  	// `Lease` is not 0, so here we just change it.
   464  	h.SetLease(time.Millisecond)
   465  
   466  	h.Clear()
   467  	c.Assert(h.InitStats(is), IsNil)
   468  	block0 := h.GetTableStats(tbl.Meta())
   469  	defcaus := block0.DeferredCausets
   470  	c.Assert(defcaus[1].LastAnalyzePos.GetBytes()[0], Equals, uint8(0x36))
   471  	c.Assert(defcaus[2].LastAnalyzePos.GetBytes()[0], Equals, uint8(0x37))
   472  	c.Assert(defcaus[3].LastAnalyzePos.GetBytes()[0], Equals, uint8(0x38))
   473  	h.Clear()
   474  	c.Assert(h.UFIDelate(is), IsNil)
   475  	block1 := h.GetTableStats(tbl.Meta())
   476  	assertTableEqual(c, block0, block1)
   477  	h.SetLease(0)
   478  }
   479  
   480  func (s *testStatsSuite) TestLoadStats(c *C) {
   481  	defer cleanEnv(c, s.causetstore, s.do)
   482  	testKit := testkit.NewTestKit(c, s.causetstore)
   483  	testKit.MustInterDirc("use test")
   484  	testKit.MustInterDirc("create causet t(a int, b int, c int, primary key(a), key idx(b))")
   485  	testKit.MustInterDirc("insert into t values (1,1,1),(2,2,2),(3,3,3)")
   486  
   487  	oriLease := s.do.StatsHandle().Lease()
   488  	s.do.StatsHandle().SetLease(1)
   489  	defer func() {
   490  		s.do.StatsHandle().SetLease(oriLease)
   491  	}()
   492  	testKit.MustInterDirc("analyze causet t")
   493  
   494  	is := s.do.SchemaReplicant()
   495  	tbl, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
   496  	c.Assert(err, IsNil)
   497  	blockInfo := tbl.Meta()
   498  	h := s.do.StatsHandle()
   499  	stat := h.GetTableStats(blockInfo)
   500  	hg := stat.DeferredCausets[blockInfo.DeferredCausets[0].ID].Histogram
   501  	c.Assert(hg.Len(), Greater, 0)
   502  	cms := stat.DeferredCausets[blockInfo.DeferredCausets[0].ID].CMSketch
   503  	c.Assert(cms, IsNil)
   504  	hg = stat.Indices[blockInfo.Indices[0].ID].Histogram
   505  	c.Assert(hg.Len(), Greater, 0)
   506  	cms = stat.Indices[blockInfo.Indices[0].ID].CMSketch
   507  	c.Assert(cms.TotalCount(), Greater, uint64(0))
   508  	hg = stat.DeferredCausets[blockInfo.DeferredCausets[2].ID].Histogram
   509  	c.Assert(hg.Len(), Equals, 0)
   510  	cms = stat.DeferredCausets[blockInfo.DeferredCausets[2].ID].CMSketch
   511  	c.Assert(cms, IsNil)
   512  	_, err = stat.DeferredCausetEqualRowCount(testKit.Se.GetStochastikVars().StmtCtx, types.NewIntCauset(1), blockInfo.DeferredCausets[2].ID)
   513  	c.Assert(err, IsNil)
   514  	c.Assert(h.LoadNeededHistograms(), IsNil)
   515  	stat = h.GetTableStats(blockInfo)
   516  	hg = stat.DeferredCausets[blockInfo.DeferredCausets[2].ID].Histogram
   517  	c.Assert(hg.Len(), Greater, 0)
   518  	// Following test tests whether the LoadNeededHistograms would panic.
   519  	c.Assert(failpoint.Enable("github.com/whtcorpsinc/milevadb/statistics/handle/mockGetStatsReaderFail", `return(true)`), IsNil)
   520  	err = h.LoadNeededHistograms()
   521  	c.Assert(err, NotNil)
   522  	c.Assert(failpoint.Disable("github.com/whtcorpsinc/milevadb/statistics/handle/mockGetStatsReaderFail"), IsNil)
   523  }
   524  
   525  func newStoreWithBootstrap() (ekv.CausetStorage, *petri.Petri, error) {
   526  	causetstore, err := mockstore.NewMockStore()
   527  	if err != nil {
   528  		return nil, nil, errors.Trace(err)
   529  	}
   530  	stochastik.SetSchemaLease(0)
   531  	stochastik.DisableStats4Test()
   532  	petri.RunAutoAnalyze = false
   533  	do, err := stochastik.BootstrapStochastik(causetstore)
   534  	do.SetStatsUFIDelating(true)
   535  	return causetstore, do, errors.Trace(err)
   536  }
   537  
   538  func (s *testStatsSuite) TestCorrelation(c *C) {
   539  	defer cleanEnv(c, s.causetstore, s.do)
   540  	testKit := testkit.NewTestKit(c, s.causetstore)
   541  	testKit.MustInterDirc("use test")
   542  	testKit.MustInterDirc("create causet t(c1 int primary key, c2 int)")
   543  	testKit.MustInterDirc("insert into t values(1,1),(3,12),(4,20),(2,7),(5,21)")
   544  	testKit.MustInterDirc("analyze causet t")
   545  	result := testKit.MustQuery("show stats_histograms where Table_name = 't'").Sort()
   546  	c.Assert(len(result.Rows()), Equals, 2)
   547  	c.Assert(result.Rows()[0][9], Equals, "0")
   548  	c.Assert(result.Rows()[1][9], Equals, "1")
   549  	testKit.MustInterDirc("insert into t values(8,18)")
   550  	testKit.MustInterDirc("analyze causet t")
   551  	result = testKit.MustQuery("show stats_histograms where Table_name = 't'").Sort()
   552  	c.Assert(len(result.Rows()), Equals, 2)
   553  	c.Assert(result.Rows()[0][9], Equals, "0")
   554  	c.Assert(result.Rows()[1][9], Equals, "0.828571")
   555  
   556  	testKit.MustInterDirc("truncate causet t")
   557  	result = testKit.MustQuery("show stats_histograms where Table_name = 't'").Sort()
   558  	c.Assert(len(result.Rows()), Equals, 0)
   559  	testKit.MustInterDirc("insert into t values(1,21),(3,12),(4,7),(2,20),(5,1)")
   560  	testKit.MustInterDirc("analyze causet t")
   561  	result = testKit.MustQuery("show stats_histograms where Table_name = 't'").Sort()
   562  	c.Assert(len(result.Rows()), Equals, 2)
   563  	c.Assert(result.Rows()[0][9], Equals, "0")
   564  	c.Assert(result.Rows()[1][9], Equals, "-1")
   565  	testKit.MustInterDirc("insert into t values(8,4)")
   566  	testKit.MustInterDirc("analyze causet t")
   567  	result = testKit.MustQuery("show stats_histograms where Table_name = 't'").Sort()
   568  	c.Assert(len(result.Rows()), Equals, 2)
   569  	c.Assert(result.Rows()[0][9], Equals, "0")
   570  	c.Assert(result.Rows()[1][9], Equals, "-0.942857")
   571  
   572  	testKit.MustInterDirc("truncate causet t")
   573  	testKit.MustInterDirc("insert into t values (1,1),(2,1),(3,1),(4,1),(5,1),(6,1),(7,1),(8,1),(9,1),(10,1),(11,1),(12,1),(13,1),(14,1),(15,1),(16,1),(17,1),(18,1),(19,1),(20,2),(21,2),(22,2),(23,2),(24,2),(25,2)")
   574  	testKit.MustInterDirc("analyze causet t")
   575  	result = testKit.MustQuery("show stats_histograms where Table_name = 't'").Sort()
   576  	c.Assert(len(result.Rows()), Equals, 2)
   577  	c.Assert(result.Rows()[0][9], Equals, "0")
   578  	c.Assert(result.Rows()[1][9], Equals, "1")
   579  
   580  	testKit.MustInterDirc("drop causet t")
   581  	testKit.MustInterDirc("create causet t(c1 int, c2 int)")
   582  	testKit.MustInterDirc("insert into t values(1,1),(2,7),(3,12),(4,20),(5,21),(8,18)")
   583  	testKit.MustInterDirc("analyze causet t")
   584  	result = testKit.MustQuery("show stats_histograms where Table_name = 't'").Sort()
   585  	c.Assert(len(result.Rows()), Equals, 2)
   586  	c.Assert(result.Rows()[0][9], Equals, "1")
   587  	c.Assert(result.Rows()[1][9], Equals, "0.828571")
   588  
   589  	testKit.MustInterDirc("truncate causet t")
   590  	testKit.MustInterDirc("insert into t values(1,1),(2,7),(3,12),(8,18),(4,20),(5,21)")
   591  	testKit.MustInterDirc("analyze causet t")
   592  	result = testKit.MustQuery("show stats_histograms where Table_name = 't'").Sort()
   593  	c.Assert(len(result.Rows()), Equals, 2)
   594  	c.Assert(result.Rows()[0][9], Equals, "0.828571")
   595  	c.Assert(result.Rows()[1][9], Equals, "1")
   596  
   597  	testKit.MustInterDirc("drop causet t")
   598  	testKit.MustInterDirc("create causet t(c1 int primary key, c2 int, c3 int, key idx_c2(c2))")
   599  	testKit.MustInterDirc("insert into t values(1,1,1),(2,2,2),(3,3,3)")
   600  	testKit.MustInterDirc("analyze causet t")
   601  	result = testKit.MustQuery("show stats_histograms where Table_name = 't' and Is_index = 0").Sort()
   602  	c.Assert(len(result.Rows()), Equals, 3)
   603  	c.Assert(result.Rows()[0][9], Equals, "0")
   604  	c.Assert(result.Rows()[1][9], Equals, "1")
   605  	c.Assert(result.Rows()[2][9], Equals, "1")
   606  	result = testKit.MustQuery("show stats_histograms where Table_name = 't' and Is_index = 1").Sort()
   607  	c.Assert(len(result.Rows()), Equals, 1)
   608  	c.Assert(result.Rows()[0][9], Equals, "0")
   609  }
   610  
   611  func (s *testStatsSuite) TestExtendedStatsOps(c *C) {
   612  	defer cleanEnv(c, s.causetstore, s.do)
   613  	tk := testkit.NewTestKit(c, s.causetstore)
   614  	err := tk.InterDircToErr("drop statistics s1")
   615  	c.Assert(err.Error(), Equals, "[causet:1046]No database selected")
   616  	tk.MustInterDirc("use test")
   617  	tk.MustInterDirc("create causet t(a int primary key, b int, c int, d int)")
   618  	tk.MustInterDirc("insert into t values(1,1,5,1),(2,2,4,2),(3,3,3,3),(4,4,2,4),(5,5,1,5)")
   619  	tk.MustInterDirc("analyze causet t")
   620  	err = tk.InterDircToErr("create statistics s1(correlation) on not_exist_db.t(b,c)")
   621  	c.Assert(err.Error(), Equals, "[schemaReplicant:1146]Block 'not_exist_db.t' doesn't exist")
   622  	err = tk.InterDircToErr("create statistics s1(correlation) on not_exist_tbl(b,c)")
   623  	c.Assert(err.Error(), Equals, "[schemaReplicant:1146]Block 'test.not_exist_tbl' doesn't exist")
   624  	err = tk.InterDircToErr("create statistics s1(correlation) on t(b,e)")
   625  	c.Assert(err.Error(), Equals, "[dbs:1072]column does not exist: e")
   626  	tk.MustInterDirc("create statistics s1(correlation) on t(a,b)")
   627  	tk.MustQuery("show warnings").Check(testkit.Rows(
   628  		"Warning 1105 No need to create correlation statistics on the integer primary key column",
   629  	))
   630  	tk.MustQuery("select type, column_ids, scalar_stats, blob_stats, status from allegrosql.stats_extended where stats_name = 's1' and EDB = 'test'").Check(testkit.Rows())
   631  	err = tk.InterDircToErr("create statistics s1(correlation) on t(b,c,d)")
   632  	c.Assert(err.Error(), Equals, "[causet:1815]Only support Correlation and Dependency statistics types on 2 columns")
   633  
   634  	tk.MustQuery("select type, column_ids, scalar_stats, blob_stats, status from allegrosql.stats_extended where stats_name = 's1' and EDB = 'test'").Check(testkit.Rows())
   635  	tk.MustInterDirc("create statistics s1(correlation) on t(b,c)")
   636  	tk.MustQuery("select type, column_ids, scalar_stats, blob_stats, status from allegrosql.stats_extended where stats_name = 's1' and EDB = 'test'").Check(testkit.Rows(
   637  		"2 [2,3] <nil> <nil> 0",
   638  	))
   639  	do := s.do
   640  	is := do.SchemaReplicant()
   641  	tbl, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
   642  	c.Assert(err, IsNil)
   643  	blockInfo := tbl.Meta()
   644  	do.StatsHandle().UFIDelate(is)
   645  	statsTbl := do.StatsHandle().GetTableStats(blockInfo)
   646  	c.Assert(statsTbl, NotNil)
   647  	c.Assert(statsTbl.ExtendedStats, NotNil)
   648  	c.Assert(len(statsTbl.ExtendedStats.Stats), Equals, 0)
   649  
   650  	tk.MustInterDirc("uFIDelate allegrosql.stats_extended set status = 1 where stats_name = 's1' and EDB = 'test'")
   651  	do.StatsHandle().Clear()
   652  	do.StatsHandle().UFIDelate(is)
   653  	statsTbl = do.StatsHandle().GetTableStats(blockInfo)
   654  	c.Assert(statsTbl, NotNil)
   655  	c.Assert(statsTbl.ExtendedStats, NotNil)
   656  	c.Assert(len(statsTbl.ExtendedStats.Stats), Equals, 1)
   657  
   658  	tk.MustInterDirc("drop statistics s1")
   659  	tk.MustQuery("select type, column_ids, scalar_stats, blob_stats, status from allegrosql.stats_extended where stats_name = 's1' and EDB = 'test'").Check(testkit.Rows(
   660  		"2 [2,3] <nil> <nil> 2",
   661  	))
   662  	do.StatsHandle().UFIDelate(is)
   663  	statsTbl = do.StatsHandle().GetTableStats(blockInfo)
   664  	c.Assert(statsTbl.ExtendedStats, NotNil)
   665  	c.Assert(len(statsTbl.ExtendedStats.Stats), Equals, 0)
   666  }
   667  
   668  func (s *testStatsSuite) TestAdminReloadStatistics(c *C) {
   669  	defer cleanEnv(c, s.causetstore, s.do)
   670  	tk := testkit.NewTestKit(c, s.causetstore)
   671  	tk.MustInterDirc("use test")
   672  	tk.MustInterDirc("create causet t(a int primary key, b int, c int, d int)")
   673  	tk.MustInterDirc("insert into t values(1,1,5,1),(2,2,4,2),(3,3,3,3),(4,4,2,4),(5,5,1,5)")
   674  	tk.MustInterDirc("analyze causet t")
   675  	tk.MustInterDirc("create statistics s1(correlation) on t(b,c)")
   676  	tk.MustQuery("select type, column_ids, scalar_stats, blob_stats, status from allegrosql.stats_extended where stats_name = 's1' and EDB = 'test'").Check(testkit.Rows(
   677  		"2 [2,3] <nil> <nil> 0",
   678  	))
   679  	do := s.do
   680  	is := do.SchemaReplicant()
   681  	tbl, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
   682  	c.Assert(err, IsNil)
   683  	blockInfo := tbl.Meta()
   684  	do.StatsHandle().UFIDelate(is)
   685  	statsTbl := do.StatsHandle().GetTableStats(blockInfo)
   686  	c.Assert(statsTbl, NotNil)
   687  	c.Assert(statsTbl.ExtendedStats, NotNil)
   688  	c.Assert(len(statsTbl.ExtendedStats.Stats), Equals, 0)
   689  
   690  	tk.MustInterDirc("uFIDelate allegrosql.stats_extended set status = 1 where stats_name = 's1' and EDB = 'test'")
   691  	do.StatsHandle().Clear()
   692  	do.StatsHandle().UFIDelate(is)
   693  	statsTbl = do.StatsHandle().GetTableStats(blockInfo)
   694  	c.Assert(statsTbl, NotNil)
   695  	c.Assert(statsTbl.ExtendedStats, NotNil)
   696  	c.Assert(len(statsTbl.ExtendedStats.Stats), Equals, 1)
   697  
   698  	tk.MustInterDirc("delete from allegrosql.stats_extended where stats_name = 's1' and EDB = 'test'")
   699  	do.StatsHandle().UFIDelate(is)
   700  	statsTbl = do.StatsHandle().GetTableStats(blockInfo)
   701  	c.Assert(statsTbl.ExtendedStats, NotNil)
   702  	c.Assert(len(statsTbl.ExtendedStats.Stats), Equals, 1)
   703  
   704  	tk.MustInterDirc("admin reload statistics")
   705  	statsTbl = do.StatsHandle().GetTableStats(blockInfo)
   706  	c.Assert(statsTbl.ExtendedStats, NotNil)
   707  	c.Assert(len(statsTbl.ExtendedStats.Stats), Equals, 0)
   708  }
   709  
   710  func (s *testStatsSuite) TestCorrelationStatsCompute(c *C) {
   711  	defer cleanEnv(c, s.causetstore, s.do)
   712  	tk := testkit.NewTestKit(c, s.causetstore)
   713  	tk.MustInterDirc("use test")
   714  	tk.MustInterDirc("create causet t(a int, b int, c int)")
   715  	tk.MustInterDirc("insert into t values(1,1,5),(2,2,4),(3,3,3),(4,4,2),(5,5,1)")
   716  	tk.MustInterDirc("analyze causet t")
   717  	tk.MustQuery("select type, column_ids, scalar_stats, blob_stats, status from allegrosql.stats_extended").Check(testkit.Rows())
   718  	tk.MustInterDirc("create statistics s1(correlation) on t(a,b)")
   719  	tk.MustInterDirc("create statistics s2(correlation) on t(a,c)")
   720  	tk.MustQuery("select type, column_ids, scalar_stats, blob_stats, status from allegrosql.stats_extended").Sort().Check(testkit.Rows(
   721  		"2 [1,2] <nil> <nil> 0",
   722  		"2 [1,3] <nil> <nil> 0",
   723  	))
   724  	do := s.do
   725  	is := do.SchemaReplicant()
   726  	tbl, err := is.TableByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
   727  	c.Assert(err, IsNil)
   728  	blockInfo := tbl.Meta()
   729  	do.StatsHandle().UFIDelate(is)
   730  	statsTbl := do.StatsHandle().GetTableStats(blockInfo)
   731  	c.Assert(statsTbl, NotNil)
   732  	c.Assert(statsTbl.ExtendedStats, NotNil)
   733  	c.Assert(len(statsTbl.ExtendedStats.Stats), Equals, 0)
   734  
   735  	tk.MustInterDirc("analyze causet t")
   736  	tk.MustQuery("select type, column_ids, scalar_stats, blob_stats, status from allegrosql.stats_extended").Sort().Check(testkit.Rows(
   737  		"2 [1,2] 1 <nil> 1",
   738  		"2 [1,3] -1 <nil> 1",
   739  	))
   740  	do.StatsHandle().UFIDelate(is)
   741  	statsTbl = do.StatsHandle().GetTableStats(blockInfo)
   742  	c.Assert(statsTbl, NotNil)
   743  	c.Assert(statsTbl.ExtendedStats, NotNil)
   744  	c.Assert(len(statsTbl.ExtendedStats.Stats), Equals, 2)
   745  	foundS1, foundS2 := false, false
   746  	for key, item := range statsTbl.ExtendedStats.Stats {
   747  		c.Assert(key.EDB, Equals, "test")
   748  		switch key.StatsName {
   749  		case "s1":
   750  			foundS1 = true
   751  			c.Assert(item.ScalarVals, Equals, float64(1))
   752  		case "s2":
   753  			foundS2 = true
   754  			c.Assert(item.ScalarVals, Equals, float64(-1))
   755  		default:
   756  			c.Assert("Unexpected extended stats in cache", IsNil)
   757  		}
   758  	}
   759  	c.Assert(foundS1 && foundS2, IsTrue)
   760  }