vitess.io/vitess@v0.16.2/go/mysql/endtoend/query_benchmark_test.go (about) 1 /* 2 Copyright 2019 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package endtoend 18 19 import ( 20 "context" 21 "fmt" 22 "os" 23 "sync" 24 "testing" 25 "time" 26 27 "github.com/stretchr/testify/require" 28 29 "vitess.io/vitess/go/mysql" 30 vttestpb "vitess.io/vitess/go/vt/proto/vttest" 31 "vitess.io/vitess/go/vt/vttest" 32 ) 33 34 // This file contains various long-running tests for mysql. 35 36 // BenchmarkWithRealDatabase runs a real MySQL database, and runs all kinds 37 // of benchmarks on it. To minimize overhead, we only run one database, and 38 // run all the benchmarks on it. 39 func BenchmarkWithRealDatabase(b *testing.B) { 40 // Launch MySQL. 41 // We need a Keyspace in the topology, so the DbName is set. 42 // We need a Shard too, so the database 'vttest' is created. 43 cfg := vttest.Config{ 44 Topology: &vttestpb.VTTestTopology{ 45 Keyspaces: []*vttestpb.Keyspace{ 46 { 47 Name: "vttest", 48 Shards: []*vttestpb.Shard{ 49 { 50 Name: "0", 51 DbNameOverride: "vttest", 52 }, 53 }, 54 }, 55 }, 56 }, 57 OnlyMySQL: true, 58 } 59 if err := cfg.InitSchemas("vttest", "create table a(id int, name varchar(128), primary key(id))", nil); err != nil { 60 b.Fatalf("InitSchemas failed: %v\n", err) 61 } 62 defer os.RemoveAll(cfg.SchemaDir) 63 cluster := vttest.LocalCluster{ 64 Config: cfg, 65 } 66 if err := cluster.Setup(); err != nil { 67 b.Fatalf("could not launch mysql: %v\n", err) 68 } 69 defer cluster.TearDown() 70 params := cluster.MySQLConnParams() 71 72 b.Run("Inserts", func(b *testing.B) { 73 benchmarkInserts(b, ¶ms) 74 }) 75 b.Run("ParallelReads", func(b *testing.B) { 76 benchmarkParallelReads(b, ¶ms, 10) 77 }) 78 } 79 80 func benchmarkInserts(b *testing.B, params *mysql.ConnParams) { 81 // Connect. 82 ctx := context.Background() 83 conn, err := mysql.Connect(ctx, params) 84 if err != nil { 85 b.Fatal(err) 86 } 87 defer conn.Close() 88 89 // Delete what we may already have in the database. 90 if _, err := conn.ExecuteFetch("delete from a", 0, false); err != nil { 91 b.Fatalf("delete failed: %v", err) 92 } 93 94 // Now reset timer. 95 b.ResetTimer() 96 97 // Do the insert. 98 for i := 0; i < b.N; i++ { 99 _, err := conn.ExecuteFetch(fmt.Sprintf("insert into a(id, name) values(%v, 'nice name %v')", i, i), 0, false) 100 if err != nil { 101 b.Fatalf("ExecuteFetch(%v) failed: %v", i, err) 102 } 103 } 104 } 105 106 func benchmarkParallelReads(b *testing.B, params *mysql.ConnParams, parallelCount int) { 107 ctx := context.Background() 108 wg := sync.WaitGroup{} 109 for i := 0; i < parallelCount; i++ { 110 wg.Add(1) 111 go func(i int) { 112 defer wg.Done() 113 114 conn, err := mysql.Connect(ctx, params) 115 if err != nil { 116 b.Error(err) 117 } 118 119 for j := 0; j < b.N; j++ { 120 if _, err := conn.ExecuteFetch("select * from a", 20000, true); err != nil { 121 b.Errorf("ExecuteFetch(%v, %v) failed: %v", i, j, err) 122 } 123 } 124 conn.Close() 125 }(i) 126 } 127 wg.Wait() 128 } 129 130 func BenchmarkSetVarsWithQueryHints(b *testing.B) { 131 ctx := context.Background() 132 conn, err := mysql.Connect(ctx, &connParams) 133 if err != nil { 134 b.Fatal(err) 135 } 136 137 _, err = conn.ExecuteFetch("create table t(id int primary key, name varchar(100))", 1, false) 138 require.NoError(b, err) 139 140 defer func() { 141 _, err = conn.ExecuteFetch("drop table t", 1, false) 142 require.NoError(b, err) 143 }() 144 145 for _, sleepDuration := range []time.Duration{0, 1 * time.Millisecond} { 146 b.Run(fmt.Sprintf("Sleep %d ms", sleepDuration/time.Millisecond), func(b *testing.B) { 147 for i := 0; i < b.N; i++ { 148 _, err := conn.ExecuteFetch(fmt.Sprintf("insert /*+ SET_VAR(sql_mode = ' ') SET_VAR(sql_safe_updates = 0) */ into t(id) values (%d)", i), 1, false) 149 if err != nil { 150 b.Fatal(err) 151 } 152 153 _, err = conn.ExecuteFetch(fmt.Sprintf("select /*+ SET_VAR(sql_mode = ' ') SET_VAR(sql_safe_updates = 0) */ * from t where id = %d", i), 1, false) 154 if err != nil { 155 b.Fatal(err) 156 } 157 158 _, err = conn.ExecuteFetch(fmt.Sprintf("update /*+ SET_VAR(sql_mode = ' ') SET_VAR(sql_safe_updates = 0) */ t set name = 'foo' where id = %d", i), 1, false) 159 if err != nil { 160 b.Fatal(err) 161 } 162 163 _, err = conn.ExecuteFetch(fmt.Sprintf("delete /*+ SET_VAR(sql_mode = ' ') SET_VAR(sql_safe_updates = 0) */ from t where id = %d", i), 1, false) 164 if err != nil { 165 b.Fatal(err) 166 } 167 time.Sleep(sleepDuration) 168 } 169 }) 170 } 171 } 172 173 func BenchmarkSetVarsMultipleSets(b *testing.B) { 174 ctx := context.Background() 175 conn, err := mysql.Connect(ctx, &connParams) 176 if err != nil { 177 b.Fatal(err) 178 } 179 180 _, err = conn.ExecuteFetch("create table t(id int primary key, name varchar(100))", 1, false) 181 require.NoError(b, err) 182 183 defer func() { 184 _, err = conn.ExecuteFetch("drop table t", 1, false) 185 require.NoError(b, err) 186 }() 187 188 setFunc := func() { 189 _, err = conn.ExecuteFetch("set sql_mode = '', sql_safe_updates = 0;", 1, false) 190 if err != nil { 191 b.Fatal(err) 192 } 193 } 194 195 for _, sleepDuration := range []time.Duration{0, 1 * time.Millisecond} { 196 b.Run(fmt.Sprintf("Sleep %d ms", sleepDuration/time.Millisecond), func(b *testing.B) { 197 for i := 0; i < b.N; i++ { 198 setFunc() 199 200 _, err = conn.ExecuteFetch(fmt.Sprintf("insert into t(id) values (%d)", i), 1, false) 201 if err != nil { 202 b.Fatal(err) 203 } 204 setFunc() 205 206 _, err = conn.ExecuteFetch(fmt.Sprintf("select * from t where id = %d", i), 1, false) 207 if err != nil { 208 b.Fatal(err) 209 } 210 setFunc() 211 212 _, err = conn.ExecuteFetch(fmt.Sprintf("update t set name = 'foo' where id = %d", i), 1, false) 213 if err != nil { 214 b.Fatal(err) 215 } 216 setFunc() 217 218 _, err = conn.ExecuteFetch(fmt.Sprintf("delete from t where id = %d", i), 1, false) 219 if err != nil { 220 b.Fatal(err) 221 } 222 time.Sleep(sleepDuration) 223 } 224 }) 225 } 226 } 227 228 func BenchmarkSetVarsMultipleSetsInSameStmt(b *testing.B) { 229 ctx := context.Background() 230 conn, err := mysql.Connect(ctx, &connParams) 231 if err != nil { 232 b.Fatal(err) 233 } 234 235 _, err = conn.ExecuteFetch("create table t(id int primary key, name varchar(100))", 1, false) 236 require.NoError(b, err) 237 238 defer func() { 239 _, err = conn.ExecuteFetch("drop table t", 1, false) 240 require.NoError(b, err) 241 }() 242 243 for _, sleepDuration := range []time.Duration{0, 1 * time.Millisecond} { 244 b.Run(fmt.Sprintf("Sleep %d ms", sleepDuration/time.Millisecond), func(b *testing.B) { 245 for i := 0; i < b.N; i++ { 246 _, _, err := conn.ExecuteFetchMulti(fmt.Sprintf("set sql_mode = '', sql_safe_updates = 0 ; insert into t(id) values (%d)", i), 1, false) 247 if err != nil { 248 b.Fatal(err) 249 } 250 _, _, _, err = conn.ReadQueryResult(1, false) 251 if err != nil { 252 b.Fatal(err) 253 } 254 255 _, _, err = conn.ExecuteFetchMulti(fmt.Sprintf("set sql_mode = '', sql_safe_updates = 0 ; select * from t where id = %d", i), 1, false) 256 if err != nil { 257 b.Fatal(err) 258 } 259 _, _, _, err = conn.ReadQueryResult(1, false) 260 if err != nil { 261 b.Fatal(err) 262 } 263 264 _, _, err = conn.ExecuteFetchMulti(fmt.Sprintf("set sql_mode = '', sql_safe_updates = 0 ; update t set name = 'foo' where id = %d", i), 1, false) 265 if err != nil { 266 b.Fatal(err) 267 } 268 _, _, _, err = conn.ReadQueryResult(1, false) 269 if err != nil { 270 b.Fatal(err) 271 } 272 273 _, _, err = conn.ExecuteFetchMulti(fmt.Sprintf("set sql_mode = '', sql_safe_updates = 0 ; delete from t where id = %d", i), 1, false) 274 if err != nil { 275 b.Fatal(err) 276 } 277 _, _, _, err = conn.ReadQueryResult(1, false) 278 if err != nil { 279 b.Fatal(err) 280 } 281 time.Sleep(sleepDuration) 282 } 283 }) 284 } 285 } 286 287 func BenchmarkSetVarsSingleSet(b *testing.B) { 288 ctx := context.Background() 289 conn, err := mysql.Connect(ctx, &connParams) 290 if err != nil { 291 b.Fatal(err) 292 } 293 294 _, err = conn.ExecuteFetch("set sql_mode = '', sql_safe_updates = 0", 1, false) 295 require.NoError(b, err) 296 297 _, err = conn.ExecuteFetch("create table t(id int primary key, name varchar(100))", 1, false) 298 require.NoError(b, err) 299 300 defer func() { 301 _, err = conn.ExecuteFetch("drop table t", 1, false) 302 require.NoError(b, err) 303 }() 304 305 for _, sleepDuration := range []time.Duration{0, 1 * time.Millisecond} { 306 b.Run(fmt.Sprintf("Sleep %d ms", sleepDuration/time.Millisecond), func(b *testing.B) { 307 for i := 0; i < b.N; i++ { 308 _, err = conn.ExecuteFetch(fmt.Sprintf("insert into t(id) values (%d)", i), 1, false) 309 if err != nil { 310 b.Fatal(err) 311 } 312 313 _, err = conn.ExecuteFetch(fmt.Sprintf("select * from t where id = %d", i), 1, false) 314 if err != nil { 315 b.Fatal(err) 316 } 317 318 _, err = conn.ExecuteFetch(fmt.Sprintf("update t set name = 'foo' where id = %d", i), 1, false) 319 if err != nil { 320 b.Fatal(err) 321 } 322 323 _, err = conn.ExecuteFetch(fmt.Sprintf("delete from t where id = %d", i), 1, false) 324 if err != nil { 325 b.Fatal(err) 326 } 327 time.Sleep(sleepDuration) 328 } 329 }) 330 } 331 332 }