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 := ®ionProperityClient{} 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 }