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