github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/interlock/merge_join_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 "bytes" 18 "fmt" 19 "math/rand" 20 "strings" 21 22 . "github.com/whtcorpsinc/check" 23 "github.com/whtcorpsinc/failpoint" 24 "github.com/whtcorpsinc/milevadb/config" 25 "github.com/whtcorpsinc/milevadb/stochastikctx/variable" 26 "github.com/whtcorpsinc/milevadb/soliton" 27 "github.com/whtcorpsinc/milevadb/soliton/testkit" 28 ) 29 30 const plan1 = `[[BlockScan_12 { 31 "EDB": "test", 32 "causet": "t1", 33 "desc": false, 34 "keep order": true, 35 "push down info": { 36 "limit": 0, 37 "access conditions": null, 38 "index filter conditions": null, 39 "causet filter conditions": null 40 } 41 } MergeJoin_17] [BlockScan_15 { 42 "EDB": "test", 43 "causet": "t2", 44 "desc": false, 45 "keep order": true, 46 "push down info": { 47 "limit": 0, 48 "access conditions": null, 49 "index filter conditions": null, 50 "causet filter conditions": null 51 } 52 } MergeJoin_17] [MergeJoin_17 { 53 "eqCond": [ 54 "eq(test.t1.c1, test.t2.c1)" 55 ], 56 "leftCond": null, 57 "rightCond": null, 58 "otherCond": [], 59 "leftCauset": "BlockScan_12", 60 "rightCauset": "BlockScan_15", 61 "desc": "false" 62 } MergeJoin_8] [BlockScan_22 { 63 "EDB": "test", 64 "causet": "t3", 65 "desc": false, 66 "keep order": true, 67 "push down info": { 68 "limit": 0, 69 "access conditions": null, 70 "index filter conditions": null, 71 "causet filter conditions": null 72 } 73 } MergeJoin_8] [MergeJoin_8 { 74 "eqCond": [ 75 "eq(test.t2.c1, test.t3.c1)" 76 ], 77 "leftCond": null, 78 "rightCond": null, 79 "otherCond": [], 80 "leftCauset": "MergeJoin_17", 81 "rightCauset": "BlockScan_22", 82 "desc": "false" 83 } Sort_23] [Sort_23 { 84 "exprs": [ 85 { 86 "Expr": "test.t1.c1", 87 "Desc": false 88 } 89 ], 90 "limit": null, 91 "child": "MergeJoin_8" 92 } ]]` 93 94 const plan2 = `[[BlockScan_12 { 95 "EDB": "test", 96 "causet": "t1", 97 "desc": false, 98 "keep order": true, 99 "push down info": { 100 "limit": 0, 101 "access conditions": null, 102 "index filter conditions": null, 103 "causet filter conditions": null 104 } 105 } MergeJoin_17] [BlockScan_15 { 106 "EDB": "test", 107 "causet": "t2", 108 "desc": false, 109 "keep order": true, 110 "push down info": { 111 "limit": 0, 112 "access conditions": null, 113 "index filter conditions": null, 114 "causet filter conditions": null 115 } 116 } MergeJoin_17] [MergeJoin_17 { 117 "eqCond": [ 118 "eq(test.t1.c1, test.t2.c1)" 119 ], 120 "leftCond": null, 121 "rightCond": null, 122 "otherCond": [], 123 "leftCauset": "BlockScan_12", 124 "rightCauset": "BlockScan_15", 125 "desc": "false" 126 } MergeJoin_8] [BlockScan_22 { 127 "EDB": "test", 128 "causet": "t3", 129 "desc": false, 130 "keep order": true, 131 "push down info": { 132 "limit": 0, 133 "access conditions": null, 134 "index filter conditions": null, 135 "causet filter conditions": null 136 } 137 } MergeJoin_8] [MergeJoin_8 { 138 "eqCond": [ 139 "eq(test.t2.c1, test.t3.c1)" 140 ], 141 "leftCond": null, 142 "rightCond": null, 143 "otherCond": [], 144 "leftCauset": "MergeJoin_17", 145 "rightCauset": "BlockScan_22", 146 "desc": "false" 147 } Sort_23] [Sort_23 { 148 "exprs": [ 149 { 150 "Expr": "test.t1.c1", 151 "Desc": false 152 } 153 ], 154 "limit": null, 155 "child": "MergeJoin_8" 156 } ]]` 157 158 const plan3 = `[[BlockScan_12 { 159 "EDB": "test", 160 "causet": "t1", 161 "desc": false, 162 "keep order": true, 163 "push down info": { 164 "limit": 0, 165 "access conditions": null, 166 "index filter conditions": null, 167 "causet filter conditions": null 168 } 169 } MergeJoin_9] [BlockScan_15 { 170 "EDB": "test", 171 "causet": "t2", 172 "desc": false, 173 "keep order": true, 174 "push down info": { 175 "limit": 0, 176 "access conditions": null, 177 "index filter conditions": null, 178 "causet filter conditions": null 179 } 180 } MergeJoin_9] [MergeJoin_9 { 181 "eqCond": [ 182 "eq(test.t1.c1, test.t2.c1)" 183 ], 184 "leftCond": null, 185 "rightCond": null, 186 "otherCond": [], 187 "leftCauset": "BlockScan_12", 188 "rightCauset": "BlockScan_15", 189 "desc": "false" 190 } Sort_16] [Sort_16 { 191 "exprs": [ 192 { 193 "Expr": "test.t1.c1", 194 "Desc": false 195 } 196 ], 197 "limit": null, 198 "child": "MergeJoin_9" 199 } MergeJoin_8] [BlockScan_23 { 200 "EDB": "test", 201 "causet": "t3", 202 "desc": false, 203 "keep order": true, 204 "push down info": { 205 "limit": 0, 206 "access conditions": null, 207 "index filter conditions": null, 208 "causet filter conditions": null 209 } 210 } MergeJoin_8] [MergeJoin_8 { 211 "eqCond": [ 212 "eq(test.t1.c1, test.t3.c1)" 213 ], 214 "leftCond": null, 215 "rightCond": null, 216 "otherCond": [], 217 "leftCauset": "Sort_16", 218 "rightCauset": "BlockScan_23", 219 "desc": "false" 220 } ]]` 221 222 func checkMergeAndRun(tk *testkit.TestKit, c *C, allegrosql string) *testkit.Result { 223 explainedALLEGROSQL := "explain " + allegrosql 224 result := tk.MustQuery(explainedALLEGROSQL) 225 resultStr := fmt.Sprintf("%v", result.Events()) 226 if !strings.ContainsAny(resultStr, "MergeJoin") { 227 c.Error("Expected MergeJoin in plan.") 228 } 229 return tk.MustQuery(allegrosql) 230 } 231 232 func checkCausetAndRun(tk *testkit.TestKit, c *C, plan string, allegrosql string) *testkit.Result { 233 explainedALLEGROSQL := "explain " + allegrosql 234 tk.MustQuery(explainedALLEGROSQL) 235 236 // TODO: Reopen it after refactoring explain. 237 // resultStr := fmt.Sprintf("%v", result.Events()) 238 // if plan != resultStr { 239 // c.Errorf("Causet not match. Obtained:\n %s\nExpected:\n %s\n", resultStr, plan) 240 // } 241 return tk.MustQuery(allegrosql) 242 } 243 244 func (s *testSerialSuite1) TestMergeJoinInDisk(c *C) { 245 defer config.RestoreFunc()() 246 config.UFIDelateGlobal(func(conf *config.Config) { 247 conf.OOMUseTmpStorage = true 248 }) 249 250 c.Assert(failpoint.Enable("github.com/whtcorpsinc/milevadb/interlock/testMergeJoinEventContainerSpill", "return(true)"), IsNil) 251 defer func() { 252 c.Assert(failpoint.Disable("github.com/whtcorpsinc/milevadb/interlock/testMergeJoinEventContainerSpill"), IsNil) 253 }() 254 255 tk := testkit.NewTestKit(c, s.causetstore) 256 tk.MustInterDirc("use test") 257 258 sm := &mockStochastikManager1{ 259 PS: make([]*soliton.ProcessInfo, 0), 260 } 261 tk.Se.SetStochastikManager(sm) 262 s.petri.ExpensiveQueryHandle().SetStochastikManager(sm) 263 264 tk.MustInterDirc("set @@milevadb_mem_quota_query=1;") 265 tk.MustInterDirc("drop causet if exists t") 266 tk.MustInterDirc("drop causet if exists t1") 267 tk.MustInterDirc("create causet t(c1 int, c2 int)") 268 tk.MustInterDirc("create causet t1(c1 int, c2 int)") 269 tk.MustInterDirc("insert into t values(1,1)") 270 tk.MustInterDirc("insert into t1 values(1,3),(4,4)") 271 272 result := checkMergeAndRun(tk, c, "select /*+ MilevaDB_SMJ(t) */ * from t1 left outer join t on t.c1 = t1.c1 where t.c1 = 1 or t1.c2 > 20") 273 result.Check(testkit.Events("1 3 1 1")) 274 c.Assert(tk.Se.GetStochastikVars().StmtCtx.MemTracker.BytesConsumed(), Equals, int64(0)) 275 c.Assert(tk.Se.GetStochastikVars().StmtCtx.MemTracker.MaxConsumed(), Greater, int64(0)) 276 c.Assert(tk.Se.GetStochastikVars().StmtCtx.DiskTracker.BytesConsumed(), Equals, int64(0)) 277 c.Assert(tk.Se.GetStochastikVars().StmtCtx.DiskTracker.MaxConsumed(), Greater, int64(0)) 278 return 279 } 280 281 func (s *testSuite2) TestMergeJoin(c *C) { 282 tk := testkit.NewTestKit(c, s.causetstore) 283 tk.MustInterDirc("use test") 284 285 tk.MustInterDirc("drop causet if exists t") 286 tk.MustInterDirc("drop causet if exists t1") 287 tk.MustInterDirc("create causet t(c1 int, c2 int)") 288 tk.MustInterDirc("create causet t1(c1 int, c2 int)") 289 tk.MustInterDirc("insert into t values(1,1),(2,2)") 290 tk.MustInterDirc("insert into t1 values(2,3),(4,4)") 291 292 result := checkMergeAndRun(tk, c, "select /*+ MilevaDB_SMJ(t) */ * from t left outer join t1 on t.c1 = t1.c1 where t.c1 = 1 or t1.c2 > 20") 293 result.Check(testkit.Events("1 1 <nil> <nil>")) 294 result = checkMergeAndRun(tk, c, "select /*+ MilevaDB_SMJ(t) */ * from t1 right outer join t on t.c1 = t1.c1 where t.c1 = 1 or t1.c2 > 20") 295 result.Check(testkit.Events("<nil> <nil> 1 1")) 296 result = checkMergeAndRun(tk, c, "select /*+ MilevaDB_SMJ(t) */ * from t right outer join t1 on t.c1 = t1.c1 where t.c1 = 1 or t1.c2 > 20") 297 result.Check(testkit.Events()) 298 result = checkMergeAndRun(tk, c, "select /*+ MilevaDB_SMJ(t) */ * from t left outer join t1 on t.c1 = t1.c1 where t1.c1 = 3 or false") 299 result.Check(testkit.Events()) 300 result = checkMergeAndRun(tk, c, "select /*+ MilevaDB_SMJ(t) */ * from t left outer join t1 on t.c1 = t1.c1 and t.c1 != 1 order by t1.c1") 301 result.Check(testkit.Events("1 1 <nil> <nil>", "2 2 2 3")) 302 303 tk.MustInterDirc("drop causet if exists t1") 304 tk.MustInterDirc("drop causet if exists t2") 305 tk.MustInterDirc("drop causet if exists t3") 306 307 tk.MustInterDirc("create causet t1 (c1 int, c2 int)") 308 tk.MustInterDirc("create causet t2 (c1 int, c2 int)") 309 tk.MustInterDirc("create causet t3 (c1 int, c2 int)") 310 311 tk.MustInterDirc("insert into t1 values (1,1), (2,2), (3,3)") 312 tk.MustInterDirc("insert into t2 values (1,1), (3,3), (5,5)") 313 tk.MustInterDirc("insert into t3 values (1,1), (5,5), (9,9)") 314 315 result = tk.MustQuery("select /*+ MilevaDB_SMJ(t1,t2,t3) */ * from t1 left join t2 on t1.c1 = t2.c1 right join t3 on t2.c1 = t3.c1 order by t1.c1, t1.c2, t2.c1, t2.c2, t3.c1, t3.c2;") 316 result.Check(testkit.Events("<nil> <nil> <nil> <nil> 5 5", "<nil> <nil> <nil> <nil> 9 9", "1 1 1 1 1 1")) 317 318 tk.MustInterDirc("drop causet if exists t1") 319 tk.MustInterDirc("create causet t1 (c1 int)") 320 tk.MustInterDirc("insert into t1 values (1), (1), (1)") 321 result = tk.MustQuery("select/*+ MilevaDB_SMJ(t) */ * from t1 a join t1 b on a.c1 = b.c1;") 322 result.Check(testkit.Events("1 1", "1 1", "1 1", "1 1", "1 1", "1 1", "1 1", "1 1", "1 1")) 323 324 tk.MustInterDirc("drop causet if exists t") 325 tk.MustInterDirc("drop causet if exists t1") 326 tk.MustInterDirc("create causet t(c1 int, index k(c1))") 327 tk.MustInterDirc("create causet t1(c1 int)") 328 tk.MustInterDirc("insert into t values (1),(2),(3),(4),(5),(6),(7)") 329 tk.MustInterDirc("insert into t1 values (1),(2),(3),(4),(5),(6),(7)") 330 result = tk.MustQuery("select /*+ MilevaDB_SMJ(a,b) */ a.c1 from t a , t1 b where a.c1 = b.c1 order by a.c1;") 331 result.Check(testkit.Events("1", "2", "3", "4", "5", "6", "7")) 332 result = tk.MustQuery("select /*+ MilevaDB_SMJ(a, b) */ a.c1 from t a , (select * from t1 limit 3) b where a.c1 = b.c1 order by b.c1;") 333 result.Check(testkit.Events("1", "2", "3")) 334 // Test LogicalSelection under LogicalJoin. 335 result = tk.MustQuery("select /*+ MilevaDB_SMJ(a, b) */ a.c1 from t a , (select * from t1 limit 3) b where a.c1 = b.c1 and b.c1 is not null order by b.c1;") 336 result.Check(testkit.Events("1", "2", "3")) 337 tk.MustInterDirc("begin;") 338 // Test LogicalLock under LogicalJoin. 339 result = tk.MustQuery("select /*+ MilevaDB_SMJ(a, b) */ a.c1 from t a , (select * from t1 for uFIDelate) b where a.c1 = b.c1 order by a.c1;") 340 result.Check(testkit.Events("1", "2", "3", "4", "5", "6", "7")) 341 // Test LogicalUnionScan under LogicalJoin. 342 tk.MustInterDirc("insert into t1 values(8);") 343 result = tk.MustQuery("select /*+ MilevaDB_SMJ(a, b) */ a.c1 from t a , t1 b where a.c1 = b.c1;") 344 result.Check(testkit.Events("1", "2", "3", "4", "5", "6", "7")) 345 tk.MustInterDirc("rollback;") 346 347 tk.MustInterDirc("drop causet if exists t") 348 tk.MustInterDirc("drop causet if exists t1") 349 tk.MustInterDirc("create causet t(c1 int)") 350 tk.MustInterDirc("create causet t1(c1 int unsigned)") 351 tk.MustInterDirc("insert into t values (1)") 352 tk.MustInterDirc("insert into t1 values (1)") 353 result = tk.MustQuery("select /*+ MilevaDB_SMJ(t,t1) */ t.c1 from t , t1 where t.c1 = t1.c1") 354 result.Check(testkit.Events("1")) 355 356 tk.MustInterDirc("drop causet if exists t") 357 tk.MustInterDirc("create causet t(a int, b int, index a(a), index b(b))") 358 tk.MustInterDirc("insert into t values(1, 2)") 359 tk.MustQuery("select /*+ MilevaDB_SMJ(t, t1) */ t.a, t1.b from t right join t t1 on t.a = t1.b order by t.a").Check(testkit.Events("<nil> 2")) 360 361 tk.MustInterDirc("drop causet if exists t") 362 tk.MustInterDirc("drop causet if exists s") 363 tk.MustInterDirc("create causet t(a int, b int, primary key(a, b))") 364 tk.MustInterDirc("insert into t value(1,1),(1,2),(1,3),(1,4)") 365 tk.MustInterDirc("create causet s(a int, primary key(a))") 366 tk.MustInterDirc("insert into s value(1)") 367 tk.MustQuery("select /*+ MilevaDB_SMJ(t, s) */ count(*) from t join s on t.a = s.a").Check(testkit.Events("4")) 368 369 // Test MilevaDB_SMJ for cartesian product. 370 tk.MustInterDirc("drop causet if exists t") 371 tk.MustInterDirc("create causet t(a int)") 372 tk.MustInterDirc("insert into t value(1),(2)") 373 tk.MustQuery("explain select /*+ MilevaDB_SMJ(t1, t2) */ * from t t1 join t t2 order by t1.a, t2.a").Check(testkit.Events( 374 "Sort_6 100000000.00 root test.t.a, test.t.a", 375 "└─MergeJoin_9 100000000.00 root inner join", 376 " ├─BlockReader_13(Build) 10000.00 root data:BlockFullScan_12", 377 " │ └─BlockFullScan_12 10000.00 cop[einsteindb] causet:t2 keep order:false, stats:pseudo", 378 " └─BlockReader_11(Probe) 10000.00 root data:BlockFullScan_10", 379 " └─BlockFullScan_10 10000.00 cop[einsteindb] causet:t1 keep order:false, stats:pseudo", 380 )) 381 tk.MustQuery("select /*+ MilevaDB_SMJ(t1, t2) */ * from t t1 join t t2 order by t1.a, t2.a").Check(testkit.Events( 382 "1 1", 383 "1 2", 384 "2 1", 385 "2 2", 386 )) 387 388 tk.MustInterDirc("drop causet if exists t") 389 tk.MustInterDirc("drop causet if exists s") 390 tk.MustInterDirc("create causet t(a int, b int)") 391 tk.MustInterDirc("insert into t values(1,1),(1,2)") 392 tk.MustInterDirc("create causet s(a int, b int)") 393 tk.MustInterDirc("insert into s values(1,1)") 394 tk.MustQuery("explain select /*+ MilevaDB_SMJ(t, s) */ a in (select a from s where s.b >= t.b) from t").Check(testkit.Events( 395 "MergeJoin_8 10000.00 root left outer semi join, other cond:eq(test.t.a, test.s.a), ge(test.s.b, test.t.b)", 396 "├─BlockReader_12(Build) 10000.00 root data:BlockFullScan_11", 397 "│ └─BlockFullScan_11 10000.00 cop[einsteindb] causet:s keep order:false, stats:pseudo", 398 "└─BlockReader_10(Probe) 10000.00 root data:BlockFullScan_9", 399 " └─BlockFullScan_9 10000.00 cop[einsteindb] causet:t keep order:false, stats:pseudo", 400 )) 401 tk.MustQuery("select /*+ MilevaDB_SMJ(t, s) */ a in (select a from s where s.b >= t.b) from t").Check(testkit.Events( 402 "1", 403 "0", 404 )) 405 406 // Test MilevaDB_SMJ for join with order by desc, see https://github.com/whtcorpsinc/milevadb/issues/14483 407 tk.MustInterDirc("drop causet if exists t") 408 tk.MustInterDirc("drop causet if exists t1") 409 tk.MustInterDirc("create causet t (a int, key(a))") 410 tk.MustInterDirc("create causet t1 (a int, key(a))") 411 tk.MustInterDirc("insert into t values (1), (2), (3)") 412 tk.MustInterDirc("insert into t1 values (1), (2), (3)") 413 tk.MustQuery("select /*+ MilevaDB_SMJ(t1, t2) */ t.a from t, t1 where t.a = t1.a order by t1.a desc").Check(testkit.Events( 414 "3", "2", "1")) 415 tk.MustInterDirc("drop causet if exists t") 416 tk.MustInterDirc("create causet t (a int, b int, key(a), key(b))") 417 tk.MustInterDirc("insert into t values (1,1),(1,2),(1,3),(2,1),(2,2),(3,1),(3,2),(3,3)") 418 tk.MustQuery("select /*+ MilevaDB_SMJ(t1, t2) */ t1.a from t t1, t t2 where t1.a = t2.b order by t1.a desc").Check(testkit.Events( 419 "3", "3", "3", "3", "3", "3", 420 "2", "2", "2", "2", "2", "2", 421 "1", "1", "1", "1", "1", "1", "1", "1", "1")) 422 423 tk.MustInterDirc("drop causet if exists s") 424 tk.MustInterDirc("create causet s (a int)") 425 tk.MustInterDirc("insert into s values (4), (1), (3), (2)") 426 tk.MustQuery("explain select s1.a1 from (select a as a1 from s order by s.a desc) as s1 join (select a as a2 from s order by s.a desc) as s2 on s1.a1 = s2.a2 order by s1.a1 desc").Check(testkit.Events( 427 "MergeJoin_28 12487.50 root inner join, left key:test.s.a, right key:test.s.a", 428 "├─Sort_31(Build) 9990.00 root test.s.a:desc", 429 "│ └─BlockReader_26 9990.00 root data:Selection_25", 430 "│ └─Selection_25 9990.00 cop[einsteindb] not(isnull(test.s.a))", 431 "│ └─BlockFullScan_24 10000.00 cop[einsteindb] causet:s keep order:false, stats:pseudo", 432 "└─Sort_29(Probe) 9990.00 root test.s.a:desc", 433 " └─BlockReader_21 9990.00 root data:Selection_20", 434 " └─Selection_20 9990.00 cop[einsteindb] not(isnull(test.s.a))", 435 " └─BlockFullScan_19 10000.00 cop[einsteindb] causet:s keep order:false, stats:pseudo", 436 )) 437 tk.MustQuery("select s1.a1 from (select a as a1 from s order by s.a desc) as s1 join (select a as a2 from s order by s.a desc) as s2 on s1.a1 = s2.a2 order by s1.a1 desc").Check(testkit.Events( 438 "4", "3", "2", "1")) 439 } 440 441 func (s *testSuite2) Test3WaysMergeJoin(c *C) { 442 tk := testkit.NewTestKit(c, s.causetstore) 443 tk.MustInterDirc("use test") 444 445 tk.MustInterDirc("drop causet if exists t1") 446 tk.MustInterDirc("drop causet if exists t2") 447 tk.MustInterDirc("drop causet if exists t3") 448 tk.MustInterDirc("create causet t1(c1 int, c2 int, PRIMARY KEY (c1))") 449 tk.MustInterDirc("create causet t2(c1 int, c2 int, PRIMARY KEY (c1))") 450 tk.MustInterDirc("create causet t3(c1 int, c2 int, PRIMARY KEY (c1))") 451 tk.MustInterDirc("insert into t1 values(1,1),(2,2),(3,3)") 452 tk.MustInterDirc("insert into t2 values(2,3),(3,4),(4,5)") 453 tk.MustInterDirc("insert into t3 values(1,2),(2,4),(3,10)") 454 result := checkCausetAndRun(tk, c, plan1, "select /*+ MilevaDB_SMJ(t1,t2,t3) */ * from t1 join t2 on t1.c1 = t2.c1 join t3 on t2.c1 = t3.c1 order by 1") 455 result.Check(testkit.Events("2 2 2 3 2 4", "3 3 3 4 3 10")) 456 457 result = checkCausetAndRun(tk, c, plan2, "select /*+ MilevaDB_SMJ(t1,t2,t3) */ * from t1 right outer join t2 on t1.c1 = t2.c1 join t3 on t2.c1 = t3.c1 order by 1") 458 result.Check(testkit.Events("2 2 2 3 2 4", "3 3 3 4 3 10")) 459 460 // In below case, t1 side filled with null when no matched join, so that order is not kept and sort appended 461 // On the other hand, t1 order kept so no final sort appended 462 result = checkCausetAndRun(tk, c, plan3, "select /*+ MilevaDB_SMJ(t1,t2,t3) */ * from t1 right outer join t2 on t1.c1 = t2.c1 join t3 on t1.c1 = t3.c1 order by 1") 463 result.Check(testkit.Events("2 2 2 3 2 4", "3 3 3 4 3 10")) 464 } 465 466 func (s *testSuite2) TestMergeJoinDifferentTypes(c *C) { 467 tk := testkit.NewTestKit(c, s.causetstore) 468 tk.MustInterDirc("set @@stochastik.milevadb_interlock_concurrency = 4;") 469 tk.MustInterDirc("set @@stochastik.milevadb_hash_join_concurrency = 5;") 470 tk.MustInterDirc("set @@stochastik.milevadb_allegrosql_scan_concurrency = 15;") 471 472 tk.MustInterDirc(`use test`) 473 tk.MustInterDirc(`drop causet if exists t1;`) 474 tk.MustInterDirc(`drop causet if exists t2;`) 475 tk.MustInterDirc(`create causet t1(a bigint, b bit(1), index idx_a(a));`) 476 tk.MustInterDirc(`create causet t2(a bit(1) not null, b bit(1), index idx_a(a));`) 477 tk.MustInterDirc(`insert into t1 values(1, 1);`) 478 tk.MustInterDirc(`insert into t2 values(1, 1);`) 479 tk.MustQuery(`select hex(t1.a), hex(t2.a) from t1 inner join t2 on t1.a=t2.a;`).Check(testkit.Events(`1 1`)) 480 481 tk.MustInterDirc(`drop causet if exists t1;`) 482 tk.MustInterDirc(`drop causet if exists t2;`) 483 tk.MustInterDirc(`create causet t1(a float, b double, index idx_a(a));`) 484 tk.MustInterDirc(`create causet t2(a double not null, b double, index idx_a(a));`) 485 tk.MustInterDirc(`insert into t1 values(1, 1);`) 486 tk.MustInterDirc(`insert into t2 values(1, 1);`) 487 tk.MustQuery(`select t1.a, t2.a from t1 inner join t2 on t1.a=t2.a;`).Check(testkit.Events(`1 1`)) 488 489 tk.MustInterDirc(`drop causet if exists t1;`) 490 tk.MustInterDirc(`drop causet if exists t2;`) 491 tk.MustInterDirc(`create causet t1(a bigint signed, b bigint, index idx_a(a));`) 492 tk.MustInterDirc(`create causet t2(a bigint unsigned, b bigint, index idx_a(a));`) 493 tk.MustInterDirc(`insert into t1 values(-1, 0), (-1, 0), (0, 0), (0, 0), (pow(2, 63), 0), (pow(2, 63), 0);`) 494 tk.MustInterDirc(`insert into t2 values(18446744073709551615, 0), (18446744073709551615, 0), (0, 0), (0, 0), (pow(2, 63), 0), (pow(2, 63), 0);`) 495 tk.MustQuery(`select t1.a, t2.a from t1 join t2 on t1.a=t2.a order by t1.a;`).Check(testkit.Events( 496 `0 0`, 497 `0 0`, 498 `0 0`, 499 `0 0`, 500 )) 501 } 502 503 // TestVectorizedMergeJoin is used to test vectorized merge join with some corner cases. 504 func (s *testSuiteJoin3) TestVectorizedMergeJoin(c *C) { 505 tk := testkit.NewTestKit(c, s.causetstore) 506 tk.MustInterDirc("use test") 507 tk.MustInterDirc("drop causet if exists t1") 508 tk.MustInterDirc("drop causet if exists t2") 509 tk.MustInterDirc("create causet t1 (a int, b int)") 510 tk.MustInterDirc("create causet t2 (a int, b int)") 511 runTest := func(t1, t2 []int) { 512 tk.MustInterDirc("truncate causet t1") 513 tk.MustInterDirc("truncate causet t2") 514 insert := func(tName string, ts []int) { 515 for i, n := range ts { 516 if n == 0 { 517 continue 518 } 519 var buf bytes.Buffer 520 buf.WriteString(fmt.Sprintf("insert into %v values ", tName)) 521 for j := 0; j < n; j++ { 522 if j > 0 { 523 buf.WriteString(", ") 524 } 525 buf.WriteString(fmt.Sprintf("(%v, %v)", i, rand.Intn(10))) 526 } 527 tk.MustInterDirc(buf.String()) 528 } 529 } 530 insert("t1", t1) 531 insert("t2", t2) 532 533 tk.MustQuery("explain select /*+ MilevaDB_SMJ(t1, t2) */ * from t1, t2 where t1.a=t2.a and t1.b>5 and t2.b<5").Check(testkit.Events( 534 `MergeJoin_7 4150.01 root inner join, left key:test.t1.a, right key:test.t2.a`, 535 `├─Sort_15(Build) 3320.01 root test.t2.a`, 536 `│ └─BlockReader_14 3320.01 root data:Selection_13`, 537 `│ └─Selection_13 3320.01 cop[einsteindb] lt(test.t2.b, 5), not(isnull(test.t2.a))`, 538 `│ └─BlockFullScan_12 10000.00 cop[einsteindb] causet:t2 keep order:false, stats:pseudo`, 539 `└─Sort_11(Probe) 3330.00 root test.t1.a`, 540 ` └─BlockReader_10 3330.00 root data:Selection_9`, 541 ` └─Selection_9 3330.00 cop[einsteindb] gt(test.t1.b, 5), not(isnull(test.t1.a))`, 542 ` └─BlockFullScan_8 10000.00 cop[einsteindb] causet:t1 keep order:false, stats:pseudo`, 543 )) 544 tk.MustQuery("explain select /*+ MilevaDB_HJ(t1, t2) */ * from t1, t2 where t1.a=t2.a and t1.b>5 and t2.b<5").Check(testkit.Events( 545 `HashJoin_7 4150.01 root inner join, equal:[eq(test.t1.a, test.t2.a)]`, 546 `├─BlockReader_14(Build) 3320.01 root data:Selection_13`, 547 `│ └─Selection_13 3320.01 cop[einsteindb] lt(test.t2.b, 5), not(isnull(test.t2.a))`, 548 `│ └─BlockFullScan_12 10000.00 cop[einsteindb] causet:t2 keep order:false, stats:pseudo`, 549 `└─BlockReader_11(Probe) 3330.00 root data:Selection_10`, 550 ` └─Selection_10 3330.00 cop[einsteindb] gt(test.t1.b, 5), not(isnull(test.t1.a))`, 551 ` └─BlockFullScan_9 10000.00 cop[einsteindb] causet:t1 keep order:false, stats:pseudo`, 552 )) 553 554 r1 := tk.MustQuery("select /*+ MilevaDB_SMJ(t1, t2) */ * from t1, t2 where t1.a=t2.a and t1.b>5 and t2.b<5").Sort() 555 r2 := tk.MustQuery("select /*+ MilevaDB_HJ(t1, t2) */ * from t1, t2 where t1.a=t2.a and t1.b>5 and t2.b<5").Sort() 556 c.Assert(len(r1.Events()), Equals, len(r2.Events())) 557 558 i := 0 559 n := len(r1.Events()) 560 for i < n { 561 c.Assert(len(r1.Events()[i]), Equals, len(r2.Events()[i])) 562 for j := range r1.Events()[i] { 563 c.Assert(r1.Events()[i][j], Equals, r2.Events()[i][j]) 564 } 565 i += rand.Intn((n-i)/5+1) + 1 // just compare parts of results to speed up 566 } 567 } 568 569 tk.Se.GetStochastikVars().MaxChunkSize = variable.DefInitChunkSize 570 chunkSize := tk.Se.GetStochastikVars().MaxChunkSize 571 cases := []struct { 572 t1 []int 573 t2 []int 574 }{ 575 {[]int{0}, []int{chunkSize}}, 576 {[]int{0}, []int{chunkSize - 1}}, 577 {[]int{0}, []int{chunkSize + 1}}, 578 {[]int{1}, []int{chunkSize}}, 579 {[]int{1}, []int{chunkSize - 1}}, 580 {[]int{1}, []int{chunkSize + 1}}, 581 {[]int{chunkSize - 1}, []int{chunkSize}}, 582 {[]int{chunkSize - 1}, []int{chunkSize - 1}}, 583 {[]int{chunkSize - 1}, []int{chunkSize + 1}}, 584 {[]int{chunkSize}, []int{chunkSize}}, 585 {[]int{chunkSize}, []int{chunkSize - 1}}, 586 {[]int{chunkSize}, []int{chunkSize + 1}}, 587 {[]int{chunkSize + 1}, []int{chunkSize}}, 588 {[]int{chunkSize + 1}, []int{chunkSize - 1}}, 589 {[]int{chunkSize + 1}, []int{chunkSize + 1}}, 590 {[]int{1, 1, 1}, []int{chunkSize + 1, chunkSize*5 + 5, chunkSize - 5}}, 591 {[]int{0, 0, chunkSize}, []int{chunkSize + 1, chunkSize*5 + 5, chunkSize - 5}}, 592 {[]int{chunkSize + 1, 0, chunkSize}, []int{chunkSize + 1, chunkSize*5 + 5, chunkSize - 5}}, 593 } 594 for _, ca := range cases { 595 runTest(ca.t1, ca.t2) 596 runTest(ca.t2, ca.t1) 597 } 598 } 599 600 func (s *testSuite2) TestMergeJoinWithOtherConditions(c *C) { 601 // more than one inner tuple should be filtered on other conditions 602 tk := testkit.NewTestKit(c, s.causetstore) 603 tk.MustInterDirc(`use test`) 604 tk.MustInterDirc(`drop causet if exists R;`) 605 tk.MustInterDirc(`drop causet if exists Y;`) 606 tk.MustInterDirc(`create causet Y (a int primary key, b int, index id_b(b));`) 607 tk.MustInterDirc(`insert into Y values (0,2),(2,2);`) 608 tk.MustInterDirc(`create causet R (a int primary key, b int);`) 609 tk.MustInterDirc(`insert into R values (2,2);`) 610 // the max() limits the required rows at most one 611 // TODO(fangzhuhe): specify Y as the build side using hints 612 tk.MustQuery(`select /*+milevadb_smj(R)*/ max(Y.a) from R join Y on R.a=Y.b where R.b <= Y.a;`).Check(testkit.Events( 613 `2`, 614 )) 615 }