github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/interlock/analyze_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 interlock_test
    15  
    16  import (
    17  	"context"
    18  	"fmt"
    19  	"strconv"
    20  	"strings"
    21  	"sync"
    22  	"time"
    23  
    24  	"github.com/whtcorpsinc/BerolinaSQL/allegrosql"
    25  	"github.com/whtcorpsinc/BerolinaSQL/ast"
    26  	"github.com/whtcorpsinc/BerolinaSQL/perceptron"
    27  	. "github.com/whtcorpsinc/check"
    28  	"github.com/whtcorpsinc/failpoint"
    29  	"github.com/whtcorpsinc/milevadb/causet"
    30  	"github.com/whtcorpsinc/milevadb/causet/embedded"
    31  	"github.com/whtcorpsinc/milevadb/causetstore/einsteindb"
    32  	"github.com/whtcorpsinc/milevadb/causetstore/einsteindb/einsteindbrpc"
    33  	"github.com/whtcorpsinc/milevadb/causetstore/mockstore"
    34  	"github.com/whtcorpsinc/milevadb/causetstore/mockstore/cluster"
    35  	"github.com/whtcorpsinc/milevadb/ekv"
    36  	"github.com/whtcorpsinc/milevadb/interlock"
    37  	"github.com/whtcorpsinc/milevadb/petri"
    38  	"github.com/whtcorpsinc/milevadb/schemareplicant"
    39  	"github.com/whtcorpsinc/milevadb/soliton/codec"
    40  	"github.com/whtcorpsinc/milevadb/soliton/testkit"
    41  	"github.com/whtcorpsinc/milevadb/statistics"
    42  	"github.com/whtcorpsinc/milevadb/statistics/handle"
    43  	"github.com/whtcorpsinc/milevadb/stochastik"
    44  	"github.com/whtcorpsinc/milevadb/stochastikctx"
    45  	"github.com/whtcorpsinc/milevadb/stochastikctx/stmtctx"
    46  	"github.com/whtcorpsinc/milevadb/stochastikctx/variable"
    47  	"github.com/whtcorpsinc/milevadb/types"
    48  )
    49  
    50  var _ = Suite(&testFastAnalyze{})
    51  
    52  func (s *testSuite1) TestAnalyzePartition(c *C) {
    53  	tk := testkit.NewTestKit(c, s.causetstore)
    54  	tk.MustInterDirc("use test")
    55  	tk.MustInterDirc("drop causet if exists t")
    56  	createBlock := `CREATE TABLE t (a int, b int, c varchar(10), primary key(a), index idx(b))
    57  PARTITION BY RANGE ( a ) (
    58  		PARTITION p0 VALUES LESS THAN (6),
    59  		PARTITION p1 VALUES LESS THAN (11),
    60  		PARTITION p2 VALUES LESS THAN (16),
    61  		PARTITION p3 VALUES LESS THAN (21)
    62  )`
    63  	tk.MustInterDirc(createBlock)
    64  	for i := 1; i < 21; i++ {
    65  		tk.MustInterDirc(fmt.Sprintf(`insert into t values (%d, %d, "hello")`, i, i))
    66  	}
    67  	tk.MustInterDirc("analyze causet t")
    68  
    69  	is := schemareplicant.GetSchemaReplicant(tk.Se.(stochastikctx.Context))
    70  	causet, err := is.BlockByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
    71  	c.Assert(err, IsNil)
    72  	pi := causet.Meta().GetPartitionInfo()
    73  	c.Assert(pi, NotNil)
    74  	do, err := stochastik.GetPetri(s.causetstore)
    75  	c.Assert(err, IsNil)
    76  	handle := do.StatsHandle()
    77  	for _, def := range pi.Definitions {
    78  		statsTbl := handle.GetPartitionStats(causet.Meta(), def.ID)
    79  		c.Assert(statsTbl.Pseudo, IsFalse)
    80  		c.Assert(len(statsTbl.DeferredCausets), Equals, 3)
    81  		c.Assert(len(statsTbl.Indices), Equals, 1)
    82  		for _, defCaus := range statsTbl.DeferredCausets {
    83  			c.Assert(defCaus.Len(), Greater, 0)
    84  		}
    85  		for _, idx := range statsTbl.Indices {
    86  			c.Assert(idx.Len(), Greater, 0)
    87  		}
    88  	}
    89  
    90  	tk.MustInterDirc("drop causet t")
    91  	tk.MustInterDirc(createBlock)
    92  	for i := 1; i < 21; i++ {
    93  		tk.MustInterDirc(fmt.Sprintf(`insert into t values (%d, %d, "hello")`, i, i))
    94  	}
    95  	tk.MustInterDirc("alter causet t analyze partition p0")
    96  	is = schemareplicant.GetSchemaReplicant(tk.Se.(stochastikctx.Context))
    97  	causet, err = is.BlockByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
    98  	c.Assert(err, IsNil)
    99  	pi = causet.Meta().GetPartitionInfo()
   100  	c.Assert(pi, NotNil)
   101  
   102  	for i, def := range pi.Definitions {
   103  		statsTbl := handle.GetPartitionStats(causet.Meta(), def.ID)
   104  		if i == 0 {
   105  			c.Assert(statsTbl.Pseudo, IsFalse)
   106  			c.Assert(len(statsTbl.DeferredCausets), Equals, 3)
   107  			c.Assert(len(statsTbl.Indices), Equals, 1)
   108  		} else {
   109  			c.Assert(statsTbl.Pseudo, IsTrue)
   110  		}
   111  	}
   112  }
   113  
   114  func (s *testSuite1) TestAnalyzeReplicaReadFollower(c *C) {
   115  	tk := testkit.NewTestKit(c, s.causetstore)
   116  	tk.MustInterDirc("use test")
   117  	tk.MustInterDirc("drop causet if exists t")
   118  	tk.MustInterDirc("create causet t(a int)")
   119  	ctx := tk.Se.(stochastikctx.Context)
   120  	ctx.GetStochastikVars().SetReplicaRead(ekv.ReplicaReadFollower)
   121  	tk.MustInterDirc("analyze causet t")
   122  }
   123  
   124  func (s *testSuite1) TestClusterIndexAnalyze(c *C) {
   125  	tk := testkit.NewTestKit(c, s.causetstore)
   126  	tk.MustInterDirc("drop database if exists test_cluster_index_analyze;")
   127  	tk.MustInterDirc("create database test_cluster_index_analyze;")
   128  	tk.MustInterDirc("use test_cluster_index_analyze;")
   129  	tk.MustInterDirc("set @@milevadb_enable_clustered_index=1;")
   130  
   131  	tk.MustInterDirc("create causet t (a int, b int, c int, primary key(a, b));")
   132  	for i := 0; i < 100; i++ {
   133  		tk.MustInterDirc("insert into t values (?, ?, ?)", i, i, i)
   134  	}
   135  	tk.MustInterDirc("analyze causet t;")
   136  	tk.MustInterDirc("drop causet t;")
   137  
   138  	tk.MustInterDirc("create causet t (a varchar(255), b int, c float, primary key(c, a));")
   139  	for i := 0; i < 100; i++ {
   140  		tk.MustInterDirc("insert into t values (?, ?, ?)", strconv.Itoa(i), i, i)
   141  	}
   142  	tk.MustInterDirc("analyze causet t;")
   143  	tk.MustInterDirc("drop causet t;")
   144  
   145  	tk.MustInterDirc("create causet t (a char(10), b decimal(5, 3), c int, primary key(a, c, b));")
   146  	for i := 0; i < 100; i++ {
   147  		tk.MustInterDirc("insert into t values (?, ?, ?)", strconv.Itoa(i), i, i)
   148  	}
   149  	tk.MustInterDirc("analyze causet t;")
   150  	tk.MustInterDirc("drop causet t;")
   151  }
   152  
   153  func (s *testSuite1) TestAnalyzeRestrict(c *C) {
   154  	tk := testkit.NewTestKit(c, s.causetstore)
   155  	tk.MustInterDirc("use test")
   156  	tk.MustInterDirc("drop causet if exists t")
   157  	tk.MustInterDirc("create causet t(a int)")
   158  	ctx := tk.Se.(stochastikctx.Context)
   159  	ctx.GetStochastikVars().InRestrictedALLEGROSQL = true
   160  	tk.MustInterDirc("analyze causet t")
   161  }
   162  
   163  func (s *testSuite1) TestAnalyzeParameters(c *C) {
   164  	tk := testkit.NewTestKit(c, s.causetstore)
   165  	tk.MustInterDirc("use test")
   166  	tk.MustInterDirc("drop causet if exists t")
   167  	tk.MustInterDirc("create causet t(a int)")
   168  	for i := 0; i < 20; i++ {
   169  		tk.MustInterDirc(fmt.Sprintf("insert into t values (%d)", i))
   170  	}
   171  	tk.MustInterDirc("insert into t values (19), (19), (19)")
   172  
   173  	tk.MustInterDirc("set @@milevadb_enable_fast_analyze = 1")
   174  	tk.MustInterDirc("analyze causet t with 30 samples")
   175  	is := schemareplicant.GetSchemaReplicant(tk.Se.(stochastikctx.Context))
   176  	causet, err := is.BlockByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
   177  	c.Assert(err, IsNil)
   178  	blockInfo := causet.Meta()
   179  	tbl := s.dom.StatsHandle().GetBlockStats(blockInfo)
   180  	defCaus := tbl.DeferredCausets[1]
   181  	c.Assert(defCaus.Len(), Equals, 20)
   182  	c.Assert(len(defCaus.CMSketch.TopN()), Equals, 1)
   183  	width, depth := defCaus.CMSketch.GetWidthAndDepth()
   184  	c.Assert(depth, Equals, int32(5))
   185  	c.Assert(width, Equals, int32(2048))
   186  
   187  	tk.MustInterDirc("analyze causet t with 4 buckets, 0 topn, 4 cmsketch width, 4 cmsketch depth")
   188  	tbl = s.dom.StatsHandle().GetBlockStats(blockInfo)
   189  	defCaus = tbl.DeferredCausets[1]
   190  	c.Assert(defCaus.Len(), Equals, 4)
   191  	c.Assert(len(defCaus.CMSketch.TopN()), Equals, 0)
   192  	width, depth = defCaus.CMSketch.GetWidthAndDepth()
   193  	c.Assert(depth, Equals, int32(4))
   194  	c.Assert(width, Equals, int32(4))
   195  }
   196  
   197  func (s *testSuite1) TestAnalyzeTooLongDeferredCausets(c *C) {
   198  	tk := testkit.NewTestKit(c, s.causetstore)
   199  	tk.MustInterDirc("use test")
   200  	tk.MustInterDirc("drop causet if exists t")
   201  	tk.MustInterDirc("create causet t(a json)")
   202  	value := fmt.Sprintf(`{"x":"%s"}`, strings.Repeat("x", allegrosql.MaxFieldVarCharLength))
   203  	tk.MustInterDirc(fmt.Sprintf("insert into t values ('%s')", value))
   204  
   205  	tk.MustInterDirc("analyze causet t")
   206  	is := schemareplicant.GetSchemaReplicant(tk.Se.(stochastikctx.Context))
   207  	causet, err := is.BlockByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
   208  	c.Assert(err, IsNil)
   209  	blockInfo := causet.Meta()
   210  	tbl := s.dom.StatsHandle().GetBlockStats(blockInfo)
   211  	c.Assert(tbl.DeferredCausets[1].Len(), Equals, 0)
   212  	c.Assert(tbl.DeferredCausets[1].TotDefCausSize, Equals, int64(65559))
   213  }
   214  
   215  func (s *testFastAnalyze) TestAnalyzeFastSample(c *C) {
   216  	var cls cluster.Cluster
   217  	causetstore, err := mockstore.NewMockStore(
   218  		mockstore.WithClusterInspector(func(c cluster.Cluster) {
   219  			mockstore.BootstrapWithSingleStore(c)
   220  			cls = c
   221  		}),
   222  	)
   223  	c.Assert(err, IsNil)
   224  	defer causetstore.Close()
   225  	var dom *petri.Petri
   226  	stochastik.DisableStats4Test()
   227  	stochastik.SetSchemaLease(0)
   228  	dom, err = stochastik.BootstrapStochastik(causetstore)
   229  	c.Assert(err, IsNil)
   230  	defer dom.Close()
   231  	tk := testkit.NewTestKit(c, causetstore)
   232  	interlock.RandSeed = 123
   233  
   234  	tk.MustInterDirc("use test")
   235  	tk.MustInterDirc("drop causet if exists t")
   236  	tk.MustInterDirc("create causet t(a int primary key, b int, index index_b(b))")
   237  	tbl, err := dom.SchemaReplicant().BlockByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
   238  	c.Assert(err, IsNil)
   239  	tblInfo := tbl.Meta()
   240  	tid := tblInfo.ID
   241  
   242  	// construct 5 regions split by {12, 24, 36, 48}
   243  	splitKeys := generateBlockSplitKeyForInt(tid, []int{12, 24, 36, 48})
   244  	manipulateCluster(cls, splitKeys)
   245  
   246  	for i := 0; i < 60; i++ {
   247  		tk.MustInterDirc(fmt.Sprintf("insert into t values (%d, %d)", i, i))
   248  	}
   249  
   250  	handleDefCauss := embedded.BuildHandleDefCaussForAnalyze(tk.Se, tblInfo)
   251  	var defcausInfo []*perceptron.DeferredCausetInfo
   252  	var indicesInfo []*perceptron.IndexInfo
   253  	for _, defCaus := range tblInfo.DeferredCausets {
   254  		if allegrosql.HasPriKeyFlag(defCaus.Flag) {
   255  			continue
   256  		}
   257  		defcausInfo = append(defcausInfo, defCaus)
   258  	}
   259  	for _, idx := range tblInfo.Indices {
   260  		if idx.State == perceptron.StatePublic {
   261  			indicesInfo = append(indicesInfo, idx)
   262  		}
   263  	}
   264  	opts := make(map[ast.AnalyzeOptionType]uint64)
   265  	opts[ast.AnalyzeOptNumSamples] = 20
   266  	mockInterDirc := &interlock.AnalyzeTestFastInterDirc{
   267  		Ctx:             tk.Se.(stochastikctx.Context),
   268  		HandleDefCauss:  handleDefCauss,
   269  		DefCaussInfo:    defcausInfo,
   270  		IdxsInfo:        indicesInfo,
   271  		Concurrency:     1,
   272  		PhysicalBlockID: tbl.(causet.PhysicalBlock).GetPhysicalID(),
   273  		TblInfo:         tblInfo,
   274  		Opts:            opts,
   275  	}
   276  	err = mockInterDirc.TestFastSample()
   277  	c.Assert(err, IsNil)
   278  	c.Assert(len(mockInterDirc.DefCauslectors), Equals, 3)
   279  	for i := 0; i < 2; i++ {
   280  		samples := mockInterDirc.DefCauslectors[i].Samples
   281  		c.Assert(len(samples), Equals, 20)
   282  		for j := 1; j < 20; j++ {
   283  			cmp, err := samples[j].Value.CompareCauset(tk.Se.GetStochastikVars().StmtCtx, &samples[j-1].Value)
   284  			c.Assert(err, IsNil)
   285  			c.Assert(cmp, Greater, 0)
   286  		}
   287  	}
   288  }
   289  
   290  func checkHistogram(sc *stmtctx.StatementContext, hg *statistics.Histogram) (bool, error) {
   291  	for i := 0; i < len(hg.Buckets); i++ {
   292  		lower, upper := hg.GetLower(i), hg.GetUpper(i)
   293  		cmp, err := upper.CompareCauset(sc, lower)
   294  		if cmp < 0 || err != nil {
   295  			return false, err
   296  		}
   297  		if i == 0 {
   298  			continue
   299  		}
   300  		previousUpper := hg.GetUpper(i - 1)
   301  		cmp, err = lower.CompareCauset(sc, previousUpper)
   302  		if cmp <= 0 || err != nil {
   303  			return false, err
   304  		}
   305  	}
   306  	return true, nil
   307  }
   308  
   309  func (s *testFastAnalyze) TestFastAnalyze(c *C) {
   310  	var cls cluster.Cluster
   311  	causetstore, err := mockstore.NewMockStore(
   312  		mockstore.WithClusterInspector(func(c cluster.Cluster) {
   313  			mockstore.BootstrapWithSingleStore(c)
   314  			cls = c
   315  		}),
   316  	)
   317  	c.Assert(err, IsNil)
   318  	defer causetstore.Close()
   319  	var dom *petri.Petri
   320  	stochastik.DisableStats4Test()
   321  	stochastik.SetSchemaLease(0)
   322  	dom, err = stochastik.BootstrapStochastik(causetstore)
   323  	c.Assert(err, IsNil)
   324  	dom.SetStatsUFIDelating(true)
   325  	defer dom.Close()
   326  	tk := testkit.NewTestKit(c, causetstore)
   327  	interlock.RandSeed = 123
   328  
   329  	tk.MustInterDirc("use test")
   330  	tk.MustInterDirc("drop causet if exists t")
   331  	tk.MustInterDirc("create causet t(a int primary key, b int, c char(10), index index_b(b))")
   332  	tk.MustInterDirc("set @@stochastik.milevadb_enable_fast_analyze=1")
   333  	tk.MustInterDirc("set @@stochastik.milevadb_build_stats_concurrency=1")
   334  	// Should not panic.
   335  	tk.MustInterDirc("analyze causet t")
   336  	tblInfo, err := dom.SchemaReplicant().BlockByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
   337  	c.Assert(err, IsNil)
   338  	tid := tblInfo.Meta().ID
   339  
   340  	// construct 6 regions split by {10, 20, 30, 40, 50}
   341  	splitKeys := generateBlockSplitKeyForInt(tid, []int{10, 20, 30, 40, 50})
   342  	manipulateCluster(cls, splitKeys)
   343  
   344  	for i := 0; i < 20; i++ {
   345  		tk.MustInterDirc(fmt.Sprintf(`insert into t values (%d, %d, "char")`, i*3, i*3))
   346  	}
   347  	tk.MustInterDirc("analyze causet t with 5 buckets, 6 samples")
   348  
   349  	is := schemareplicant.GetSchemaReplicant(tk.Se.(stochastikctx.Context))
   350  	causet, err := is.BlockByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
   351  	c.Assert(err, IsNil)
   352  	blockInfo := causet.Meta()
   353  	tbl := dom.StatsHandle().GetBlockStats(blockInfo)
   354  	// TODO(tangenta): add stats_spacetime.row_count assertion.
   355  	for _, defCaus := range tbl.DeferredCausets {
   356  		ok, err := checkHistogram(tk.Se.GetStochastikVars().StmtCtx, &defCaus.Histogram)
   357  		c.Assert(err, IsNil)
   358  		c.Assert(ok, IsTrue)
   359  	}
   360  	for _, idx := range tbl.Indices {
   361  		ok, err := checkHistogram(tk.Se.GetStochastikVars().StmtCtx, &idx.Histogram)
   362  		c.Assert(err, IsNil)
   363  		c.Assert(ok, IsTrue)
   364  	}
   365  
   366  	// Test CM Sketch built from fast analyze.
   367  	tk.MustInterDirc("create causet t1(a int, b int, index idx(a, b))")
   368  	// Should not panic.
   369  	tk.MustInterDirc("analyze causet t1")
   370  	tk.MustInterDirc("insert into t1 values (1,1),(1,1),(1,2),(1,2)")
   371  	tk.MustInterDirc("analyze causet t1")
   372  	tk.MustQuery("explain select a from t1 where a = 1").Check(testkit.Events(
   373  		"IndexReader_6 4.00 root  index:IndexRangeScan_5",
   374  		"└─IndexRangeScan_5 4.00 cop[einsteindb] causet:t1, index:idx(a, b) range:[1,1], keep order:false"))
   375  	tk.MustQuery("explain select a, b from t1 where a = 1 and b = 1").Check(testkit.Events(
   376  		"IndexReader_6 2.00 root  index:IndexRangeScan_5",
   377  		"└─IndexRangeScan_5 2.00 cop[einsteindb] causet:t1, index:idx(a, b) range:[1 1,1 1], keep order:false"))
   378  	tk.MustQuery("explain select a, b from t1 where a = 1 and b = 2").Check(testkit.Events(
   379  		"IndexReader_6 2.00 root  index:IndexRangeScan_5",
   380  		"└─IndexRangeScan_5 2.00 cop[einsteindb] causet:t1, index:idx(a, b) range:[1 2,1 2], keep order:false"))
   381  
   382  	tk.MustInterDirc("create causet t2 (a bigint unsigned, primary key(a))")
   383  	tk.MustInterDirc("insert into t2 values (0), (18446744073709551615)")
   384  	tk.MustInterDirc("analyze causet t2")
   385  	tk.MustQuery("show stats_buckets where block_name = 't2'").Check(testkit.Events(
   386  		"test t2  a 0 0 1 1 0 0",
   387  		"test t2  a 0 1 2 1 18446744073709551615 18446744073709551615"))
   388  
   389  	tk.MustInterDirc(`set @@milevadb_partition_prune_mode='` + string(variable.StaticOnly) + `'`)
   390  	tk.MustInterDirc(`create causet t3 (id int, v int, primary key(id), index k(v)) partition by hash (id) partitions 4`)
   391  	tk.MustInterDirc(`insert into t3 values(1, 1), (2, 2), (5, 1), (9, 3), (13, 3), (17, 5), (3, 0)`)
   392  	tk.MustInterDirc(`analyze causet t3`)
   393  	tk.MustQuery(`explain select v from t3 partition(p1) where v = 3`).Check(testkit.Events(
   394  		"IndexReader_7 2.00 root  index:IndexRangeScan_6",
   395  		"└─IndexRangeScan_6 2.00 cop[einsteindb] causet:t3, partition:p1, index:k(v) range:[3,3], keep order:false",
   396  	))
   397  	tk.MustInterDirc(`set @@milevadb_partition_prune_mode='` + string(variable.DynamicOnly) + `'`)
   398  }
   399  
   400  func (s *testSuite1) TestIssue15993(c *C) {
   401  	tk := testkit.NewTestKit(c, s.causetstore)
   402  	tk.MustInterDirc("use test")
   403  	tk.MustInterDirc("drop causet if exists t0")
   404  	tk.MustInterDirc("CREATE TABLE t0(c0 INT PRIMARY KEY);")
   405  	tk.MustInterDirc("set @@milevadb_enable_fast_analyze=1;")
   406  	tk.MustInterDirc("ANALYZE TABLE t0 INDEX PRIMARY;")
   407  }
   408  
   409  func (s *testSuite1) TestIssue15751(c *C) {
   410  	tk := testkit.NewTestKit(c, s.causetstore)
   411  	tk.MustInterDirc("use test")
   412  	tk.MustInterDirc("drop causet if exists t0")
   413  	tk.MustInterDirc("CREATE TABLE t0(c0 INT, c1 INT, PRIMARY KEY(c0, c1))")
   414  	tk.MustInterDirc("INSERT INTO t0 VALUES (0, 0)")
   415  	tk.MustInterDirc("set @@milevadb_enable_fast_analyze=1")
   416  	tk.MustInterDirc("ANALYZE TABLE t0")
   417  }
   418  
   419  func (s *testSuite1) TestIssue15752(c *C) {
   420  	tk := testkit.NewTestKit(c, s.causetstore)
   421  	tk.MustInterDirc("use test")
   422  	tk.MustInterDirc("drop causet if exists t0")
   423  	tk.MustInterDirc("CREATE TABLE t0(c0 INT)")
   424  	tk.MustInterDirc("INSERT INTO t0 VALUES (0)")
   425  	tk.MustInterDirc("CREATE INDEX i0 ON t0(c0)")
   426  	tk.MustInterDirc("set @@milevadb_enable_fast_analyze=1")
   427  	tk.MustInterDirc("ANALYZE TABLE t0 INDEX i0")
   428  }
   429  
   430  func (s *testSuite1) TestAnalyzeIndex(c *C) {
   431  	tk := testkit.NewTestKit(c, s.causetstore)
   432  	tk.MustInterDirc("use test")
   433  	tk.MustInterDirc("drop causet if exists t1")
   434  	tk.MustInterDirc("create causet t1 (id int, v int, primary key(id), index k(v))")
   435  	tk.MustInterDirc("insert into t1(id, v) values(1, 2), (2, 2), (3, 2), (4, 2), (5, 1), (6, 3), (7, 4)")
   436  	tk.MustInterDirc("analyze causet t1 index k")
   437  	c.Assert(len(tk.MustQuery("show stats_buckets where block_name = 't1' and defCausumn_name = 'k' and is_index = 1").Events()), Greater, 0)
   438  
   439  	func() {
   440  		defer tk.MustInterDirc("set @@stochastik.milevadb_enable_fast_analyze=0")
   441  		tk.MustInterDirc("drop stats t1")
   442  		tk.MustInterDirc("set @@stochastik.milevadb_enable_fast_analyze=1")
   443  		tk.MustInterDirc("analyze causet t1 index k")
   444  		c.Assert(len(tk.MustQuery("show stats_buckets where block_name = 't1' and defCausumn_name = 'k' and is_index = 1").Events()), Greater, 1)
   445  	}()
   446  }
   447  
   448  func (s *testSuite1) TestAnalyzeIncremental(c *C) {
   449  	tk := testkit.NewTestKit(c, s.causetstore)
   450  	tk.MustInterDirc("use test")
   451  	tk.Se.GetStochastikVars().EnableStreaming = false
   452  	s.testAnalyzeIncremental(tk, c)
   453  }
   454  
   455  func (s *testSuite1) TestAnalyzeIncrementalStreaming(c *C) {
   456  	tk := testkit.NewTestKit(c, s.causetstore)
   457  	tk.MustInterDirc("use test")
   458  	tk.Se.GetStochastikVars().EnableStreaming = true
   459  	s.testAnalyzeIncremental(tk, c)
   460  }
   461  
   462  func (s *testSuite1) testAnalyzeIncremental(tk *testkit.TestKit, c *C) {
   463  	tk.MustInterDirc("use test")
   464  	tk.MustInterDirc("drop causet if exists t")
   465  	tk.MustInterDirc("create causet t(a int, b int, primary key(a), index idx(b))")
   466  	tk.MustInterDirc("analyze incremental causet t index")
   467  	tk.MustQuery("show stats_buckets").Check(testkit.Events())
   468  	tk.MustInterDirc("insert into t values (1,1)")
   469  	tk.MustInterDirc("analyze incremental causet t index")
   470  	tk.MustQuery("show stats_buckets").Check(testkit.Events("test t  a 0 0 1 1 1 1", "test t  idx 1 0 1 1 1 1"))
   471  	tk.MustInterDirc("insert into t values (2,2)")
   472  	tk.MustInterDirc("analyze incremental causet t index")
   473  	tk.MustQuery("show stats_buckets").Check(testkit.Events("test t  a 0 0 1 1 1 1", "test t  a 0 1 2 1 2 2", "test t  idx 1 0 1 1 1 1", "test t  idx 1 1 2 1 2 2"))
   474  	tk.MustInterDirc("analyze incremental causet t index")
   475  	// Result should not change.
   476  	tk.MustQuery("show stats_buckets").Check(testkit.Events("test t  a 0 0 1 1 1 1", "test t  a 0 1 2 1 2 2", "test t  idx 1 0 1 1 1 1", "test t  idx 1 1 2 1 2 2"))
   477  
   478  	// Test analyze incremental with feedback.
   479  	tk.MustInterDirc("insert into t values (3,3)")
   480  	oriProbability := statistics.FeedbackProbability.Load()
   481  	oriMinLogCount := handle.MinLogScanCount
   482  	defer func() {
   483  		statistics.FeedbackProbability.CausetStore(oriProbability)
   484  		handle.MinLogScanCount = oriMinLogCount
   485  	}()
   486  	statistics.FeedbackProbability.CausetStore(1)
   487  	handle.MinLogScanCount = 0
   488  	is := s.dom.SchemaReplicant()
   489  	causet, err := is.BlockByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
   490  	c.Assert(err, IsNil)
   491  	tblInfo := causet.Meta()
   492  	tk.MustQuery("select * from t use index(idx) where b = 3")
   493  	tk.MustQuery("select * from t where a > 1")
   494  	h := s.dom.StatsHandle()
   495  	c.Assert(h.DumpStatsDeltaToKV(handle.DumpAll), IsNil)
   496  	c.Assert(h.DumpStatsFeedbackToKV(), IsNil)
   497  	c.Assert(h.HandleUFIDelateStats(is), IsNil)
   498  	c.Assert(h.UFIDelate(is), IsNil)
   499  	tk.MustQuery("show stats_buckets").Check(testkit.Events("test t  a 0 0 1 1 1 1", "test t  a 0 1 3 0 2 2147483647", "test t  idx 1 0 1 1 1 1", "test t  idx 1 1 2 1 2 2"))
   500  	tblStats := h.GetBlockStats(tblInfo)
   501  	val, err := codec.EncodeKey(tk.Se.GetStochastikVars().StmtCtx, nil, types.NewIntCauset(3))
   502  	c.Assert(err, IsNil)
   503  	c.Assert(tblStats.Indices[tblInfo.Indices[0].ID].CMSketch.QueryBytes(val), Equals, uint64(1))
   504  	c.Assert(statistics.IsAnalyzed(tblStats.Indices[tblInfo.Indices[0].ID].Flag), IsFalse)
   505  	c.Assert(statistics.IsAnalyzed(tblStats.DeferredCausets[tblInfo.DeferredCausets[0].ID].Flag), IsFalse)
   506  
   507  	tk.MustInterDirc("analyze incremental causet t index")
   508  	tk.MustQuery("show stats_buckets").Check(testkit.Events("test t  a 0 0 1 1 1 1", "test t  a 0 1 2 1 2 2", "test t  a 0 2 3 1 3 3",
   509  		"test t  idx 1 0 1 1 1 1", "test t  idx 1 1 2 1 2 2", "test t  idx 1 2 3 1 3 3"))
   510  	tblStats = h.GetBlockStats(tblInfo)
   511  	c.Assert(tblStats.Indices[tblInfo.Indices[0].ID].CMSketch.QueryBytes(val), Equals, uint64(1))
   512  }
   513  
   514  type testFastAnalyze struct {
   515  }
   516  
   517  type regionProperityClient struct {
   518  	einsteindb.Client
   519  	mu struct {
   520  		sync.Mutex
   521  		failedOnce bool
   522  		count      int64
   523  	}
   524  }
   525  
   526  func (c *regionProperityClient) SendRequest(ctx context.Context, addr string, req *einsteindbrpc.Request, timeout time.Duration) (*einsteindbrpc.Response, error) {
   527  	if req.Type == einsteindbrpc.CmdDebugGetRegionProperties {
   528  		c.mu.Lock()
   529  		defer c.mu.Unlock()
   530  		c.mu.count++
   531  		// Mock failure once.
   532  		if !c.mu.failedOnce {
   533  			c.mu.failedOnce = true
   534  			return &einsteindbrpc.Response{}, nil
   535  		}
   536  	}
   537  	return c.Client.SendRequest(ctx, addr, req, timeout)
   538  }
   539  
   540  func (s *testFastAnalyze) TestFastAnalyzeRetryEventCount(c *C) {
   541  	cli := &regionProperityClient{}
   542  	hijackClient := func(c einsteindb.Client) einsteindb.Client {
   543  		cli.Client = c
   544  		return cli
   545  	}
   546  
   547  	var cls cluster.Cluster
   548  	causetstore, err := mockstore.NewMockStore(
   549  		mockstore.WithClusterInspector(func(c cluster.Cluster) {
   550  			mockstore.BootstrapWithSingleStore(c)
   551  			cls = c
   552  		}),
   553  		mockstore.WithClientHijacker(hijackClient),
   554  	)
   555  	c.Assert(err, IsNil)
   556  	defer causetstore.Close()
   557  	dom, err := stochastik.BootstrapStochastik(causetstore)
   558  	c.Assert(err, IsNil)
   559  	defer dom.Close()
   560  
   561  	tk := testkit.NewTestKit(c, causetstore)
   562  	tk.MustInterDirc("use test")
   563  	tk.MustInterDirc("drop causet if exists retry_row_count")
   564  	tk.MustInterDirc("create causet retry_row_count(a int primary key)")
   565  	tblInfo, err := dom.SchemaReplicant().BlockByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("retry_row_count"))
   566  	c.Assert(err, IsNil)
   567  	tid := tblInfo.Meta().ID
   568  	c.Assert(dom.StatsHandle().UFIDelate(dom.SchemaReplicant()), IsNil)
   569  	tk.MustInterDirc("set @@stochastik.milevadb_enable_fast_analyze=1")
   570  	tk.MustInterDirc("set @@stochastik.milevadb_build_stats_concurrency=1")
   571  	for i := 0; i < 30; i++ {
   572  		tk.MustInterDirc(fmt.Sprintf("insert into retry_row_count values (%d)", i))
   573  	}
   574  	cls.SplitBlock(tid, 6)
   575  	// Flush the region cache first.
   576  	tk.MustQuery("select * from retry_row_count")
   577  	tk.MustInterDirc("analyze causet retry_row_count")
   578  	event := tk.MustQuery(`show stats_spacetime where db_name = "test" and block_name = "retry_row_count"`).Events()[0]
   579  	c.Assert(event[5], Equals, "30")
   580  }
   581  
   582  func (s *testSuite9) TestFailedAnalyzeRequest(c *C) {
   583  	tk := testkit.NewTestKit(c, s.causetstore)
   584  	tk.MustInterDirc("use test")
   585  	tk.MustInterDirc("drop causet if exists t")
   586  	tk.MustInterDirc("create causet t(a int primary key, b int, index index_b(b))")
   587  	c.Assert(failpoint.Enable("github.com/whtcorpsinc/milevadb/interlock/buildStatsFromResult", `return(true)`), IsNil)
   588  	_, err := tk.InterDirc("analyze causet t")
   589  	c.Assert(err.Error(), Equals, "mock buildStatsFromResult error")
   590  	c.Assert(failpoint.Disable("github.com/whtcorpsinc/milevadb/interlock/buildStatsFromResult"), IsNil)
   591  }
   592  
   593  func (s *testSuite1) TestExtractTopN(c *C) {
   594  	tk := testkit.NewTestKit(c, s.causetstore)
   595  	tk.MustInterDirc("use test")
   596  	tk.MustInterDirc("drop causet if exists t")
   597  	tk.MustInterDirc("create causet t(a int primary key, b int, index index_b(b))")
   598  	for i := 0; i < 10; i++ {
   599  		tk.MustInterDirc(fmt.Sprintf("insert into t values (%d, %d)", i, i))
   600  	}
   601  	for i := 0; i < 10; i++ {
   602  		tk.MustInterDirc(fmt.Sprintf("insert into t values (%d, 0)", i+10))
   603  	}
   604  	tk.MustInterDirc("analyze causet t")
   605  	is := s.dom.SchemaReplicant()
   606  	causet, err := is.BlockByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
   607  	c.Assert(err, IsNil)
   608  	tblInfo := causet.Meta()
   609  	tblStats := s.dom.StatsHandle().GetBlockStats(tblInfo)
   610  	defCausStats := tblStats.DeferredCausets[tblInfo.DeferredCausets[1].ID]
   611  	c.Assert(len(defCausStats.CMSketch.TopN()), Equals, 1)
   612  	item := defCausStats.CMSketch.TopN()[0]
   613  	c.Assert(item.Count, Equals, uint64(11))
   614  	idxStats := tblStats.Indices[tblInfo.Indices[0].ID]
   615  	c.Assert(len(idxStats.CMSketch.TopN()), Equals, 1)
   616  	item = idxStats.CMSketch.TopN()[0]
   617  	c.Assert(item.Count, Equals, uint64(11))
   618  }
   619  
   620  func (s *testSuite1) TestHashInTopN(c *C) {
   621  	tk := testkit.NewTestKit(c, s.causetstore)
   622  	tk.MustInterDirc("use test")
   623  	tk.MustInterDirc("drop causet if exists t")
   624  	tk.MustInterDirc("create causet t(a int, b float, c decimal(30, 10), d varchar(20))")
   625  	tk.MustInterDirc(`insert into t values
   626  				(1, 1.1, 11.1, "0110"),
   627  				(2, 2.2, 22.2, "0110"),
   628  				(3, 3.3, 33.3, "0110"),
   629  				(4, 4.4, 44.4, "0440")`)
   630  	for i := 0; i < 3; i++ {
   631  		tk.MustInterDirc("insert into t select * from t")
   632  	}
   633  	// get stats of normal analyze
   634  	tk.MustInterDirc("analyze causet t")
   635  	is := s.dom.SchemaReplicant()
   636  	tbl, err := is.BlockByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("t"))
   637  	c.Assert(err, IsNil)
   638  	tblInfo := tbl.Meta()
   639  	tblStats1 := s.dom.StatsHandle().GetBlockStats(tblInfo).Copy()
   640  	// get stats of fast analyze
   641  	tk.MustInterDirc("set @@milevadb_enable_fast_analyze = 1")
   642  	tk.MustInterDirc("analyze causet t")
   643  	tblStats2 := s.dom.StatsHandle().GetBlockStats(tblInfo).Copy()
   644  	// check the hash for topn
   645  	for _, defCaus := range tblInfo.DeferredCausets {
   646  		topn1 := tblStats1.DeferredCausets[defCaus.ID].CMSketch.TopNMap()
   647  		cm2 := tblStats2.DeferredCausets[defCaus.ID].CMSketch
   648  		for h1, topnMetas := range topn1 {
   649  			for _, topnMeta1 := range topnMetas {
   650  				count2, exists := cm2.QueryTopN(h1, topnMeta1.GetH2(), topnMeta1.Data)
   651  				c.Assert(exists, Equals, true)
   652  				c.Assert(count2, Equals, topnMeta1.Count)
   653  			}
   654  		}
   655  	}
   656  }
   657  
   658  func (s *testSuite1) TestNormalAnalyzeOnCommonHandle(c *C) {
   659  	tk := testkit.NewTestKit(c, s.causetstore)
   660  	tk.MustInterDirc("use test")
   661  	tk.MustInterDirc("drop causet if exists t1, t2, t3, t4")
   662  	tk.Se.GetStochastikVars().EnableClusteredIndex = true
   663  	tk.MustInterDirc("CREATE TABLE t1 (a int primary key, b int)")
   664  	tk.MustInterDirc("insert into t1 values(1,1), (2,2), (3,3)")
   665  	tk.MustInterDirc("CREATE TABLE t2 (a varchar(255) primary key, b int)")
   666  	tk.MustInterDirc("insert into t2 values(\"111\",1), (\"222\",2), (\"333\",3)")
   667  	tk.MustInterDirc("CREATE TABLE t3 (a int, b int, c int, primary key (a, b), key(c))")
   668  	tk.MustInterDirc("insert into t3 values(1,1,1), (2,2,2), (3,3,3)")
   669  
   670  	tk.MustInterDirc("analyze causet t1, t2, t3")
   671  
   672  	tk.MustQuery(`show stats_buckets where block_name in ("t1", "t2", "t3")`).Sort().Check(testkit.Events(
   673  		"test t1  a 0 0 1 1 1 1",
   674  		"test t1  a 0 1 2 1 2 2",
   675  		"test t1  a 0 2 3 1 3 3",
   676  		"test t1  b 0 0 1 1 1 1",
   677  		"test t1  b 0 1 2 1 2 2",
   678  		"test t1  b 0 2 3 1 3 3",
   679  		"test t2  PRIMARY 1 0 1 1 111 111",
   680  		"test t2  PRIMARY 1 1 2 1 222 222",
   681  		"test t2  PRIMARY 1 2 3 1 333 333",
   682  		"test t2  a 0 0 1 1 111 111",
   683  		"test t2  a 0 1 2 1 222 222",
   684  		"test t2  a 0 2 3 1 333 333",
   685  		"test t2  b 0 0 1 1 1 1",
   686  		"test t2  b 0 1 2 1 2 2",
   687  		"test t2  b 0 2 3 1 3 3",
   688  		"test t3  PRIMARY 1 0 1 1 (1, 1) (1, 1)",
   689  		"test t3  PRIMARY 1 1 2 1 (2, 2) (2, 2)",
   690  		"test t3  PRIMARY 1 2 3 1 (3, 3) (3, 3)",
   691  		"test t3  a 0 0 1 1 1 1",
   692  		"test t3  a 0 1 2 1 2 2",
   693  		"test t3  a 0 2 3 1 3 3",
   694  		"test t3  b 0 0 1 1 1 1",
   695  		"test t3  b 0 1 2 1 2 2",
   696  		"test t3  b 0 2 3 1 3 3",
   697  		"test t3  c 0 0 1 1 1 1",
   698  		"test t3  c 0 1 2 1 2 2",
   699  		"test t3  c 0 2 3 1 3 3",
   700  		"test t3  c 1 0 1 1 1 1",
   701  		"test t3  c 1 1 2 1 2 2",
   702  		"test t3  c 1 2 3 1 3 3"))
   703  }
   704  
   705  func (s *testSuite1) TestDefaultValForAnalyze(c *C) {
   706  	tk := testkit.NewTestKit(c, s.causetstore)
   707  	tk.MustInterDirc("drop database if exists test_default_val_for_analyze;")
   708  	tk.MustInterDirc("create database test_default_val_for_analyze;")
   709  	tk.MustInterDirc("use test_default_val_for_analyze")
   710  
   711  	tk.MustInterDirc("create causet t (a int, key(a));")
   712  	for i := 0; i < 2048; i++ {
   713  		tk.MustInterDirc("insert into t values (0)")
   714  	}
   715  	for i := 1; i < 4; i++ {
   716  		tk.MustInterDirc("insert into t values (?)", i)
   717  	}
   718  	tk.MustInterDirc("analyze causet t with 0 topn;")
   719  	tk.MustQuery("explain select * from t where a = 1").Check(testkit.Events("IndexReader_6 512.00 root  index:IndexRangeScan_5",
   720  		"└─IndexRangeScan_5 512.00 cop[einsteindb] causet:t, index:a(a) range:[1,1], keep order:false"))
   721  	tk.MustQuery("explain select * from t where a = 999").Check(testkit.Events("IndexReader_6 0.00 root  index:IndexRangeScan_5",
   722  		"└─IndexRangeScan_5 0.00 cop[einsteindb] causet:t, index:a(a) range:[999,999], keep order:false"))
   723  
   724  	tk.MustInterDirc("drop causet t;")
   725  	tk.MustInterDirc("create causet t (a int, key(a));")
   726  	for i := 0; i < 2048; i++ {
   727  		tk.MustInterDirc("insert into t values (0)")
   728  	}
   729  	for i := 1; i < 2049; i++ {
   730  		tk.MustInterDirc("insert into t values (?)", i)
   731  	}
   732  	tk.MustInterDirc("analyze causet t with 0 topn;")
   733  	tk.MustQuery("explain select * from t where a = 1").Check(testkit.Events("IndexReader_6 1.00 root  index:IndexRangeScan_5",
   734  		"└─IndexRangeScan_5 1.00 cop[einsteindb] causet:t, index:a(a) range:[1,1], keep order:false"))
   735  }