github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/bench/fk_test.go (about) 1 // Copyright 2019 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package bench 12 13 import ( 14 "context" 15 "fmt" 16 "strings" 17 "testing" 18 19 "github.com/cockroachdb/cockroach/pkg/base" 20 "github.com/cockroachdb/cockroach/pkg/testutils/serverutils" 21 "github.com/cockroachdb/cockroach/pkg/testutils/sqlutils" 22 ) 23 24 func runFKBench( 25 b *testing.B, 26 setup func(b *testing.B, r *sqlutils.SQLRunner, setupFKs bool), 27 run func(b *testing.B, r *sqlutils.SQLRunner), 28 ) { 29 configs := []struct { 30 name string 31 setupFKs bool 32 optFKOn bool 33 insertFastPath bool 34 }{ 35 {name: "None", setupFKs: false}, 36 {name: "Old", setupFKs: true, optFKOn: false}, 37 {name: "New", setupFKs: true, optFKOn: true, insertFastPath: false}, 38 {name: "FastPath", setupFKs: true, optFKOn: true, insertFastPath: true}, 39 } 40 41 for _, cfg := range configs { 42 b.Run(cfg.name, func(b *testing.B) { 43 s, db, _ := serverutils.StartServer(b, base.TestServerArgs{}) 44 defer s.Stopper().Stop(context.Background()) 45 r := sqlutils.MakeSQLRunner(db) 46 // Don't let auto stats interfere with the test. Stock stats are 47 // sufficient to get the right plans (i.e. lookup join). 48 r.Exec(b, "SET CLUSTER SETTING sql.stats.automatic_collection.enabled = false") 49 r.Exec(b, fmt.Sprintf("SET optimizer_foreign_keys = %v", cfg.optFKOn)) 50 r.Exec(b, fmt.Sprintf("SET enable_insert_fast_path = %v", cfg.insertFastPath)) 51 setup(b, r, cfg.setupFKs) 52 b.ResetTimer() 53 run(b, r) 54 }) 55 } 56 } 57 58 func BenchmarkFKInsert(b *testing.B) { 59 const parentRows = 1000 60 setup := func(b *testing.B, r *sqlutils.SQLRunner, setupFKs bool) { 61 r.Exec(b, "CREATE TABLE child (k int primary key, p int)") 62 r.Exec(b, "CREATE TABLE parent (p int primary key, data int)") 63 64 if setupFKs { 65 r.Exec(b, "ALTER TABLE child ADD CONSTRAINT fk FOREIGN KEY (p) REFERENCES parent(p)") 66 } else { 67 // Create the index on p manually so it's a more fair comparison. 68 r.Exec(b, "CREATE INDEX idx ON child(p)") 69 } 70 71 r.Exec(b, fmt.Sprintf( 72 "INSERT INTO parent SELECT i, i FROM generate_series(0,%d) AS g(i)", parentRows-1, 73 )) 74 } 75 76 b.Run("SingleRow", func(b *testing.B) { 77 runFKBench(b, setup, func(b *testing.B, r *sqlutils.SQLRunner) { 78 for i := 0; i < b.N; i++ { 79 r.Exec(b, fmt.Sprintf("INSERT INTO child VALUES (%d, %d)", i, i%parentRows)) 80 } 81 }) 82 }) 83 84 const batch = 20 85 b.Run("MultiRowSingleParent", func(b *testing.B) { 86 runFKBench(b, setup, func(b *testing.B, r *sqlutils.SQLRunner) { 87 k := 0 88 for i := 0; i < b.N; i++ { 89 // All rows in the batch reference the same parent value. 90 parent := i % parentRows 91 vals := make([]string, batch) 92 for j := range vals { 93 vals[j] = fmt.Sprintf("(%d, %d)", k, parent) 94 k++ 95 } 96 r.Exec(b, fmt.Sprintf("INSERT INTO child VALUES %s", strings.Join(vals, ","))) 97 } 98 }) 99 }) 100 101 b.Run("MultiRowMultiParent", func(b *testing.B) { 102 runFKBench(b, setup, func(b *testing.B, r *sqlutils.SQLRunner) { 103 k := 0 104 for i := 0; i < b.N; i++ { 105 vals := make([]string, batch) 106 for j := range vals { 107 vals[j] = fmt.Sprintf("(%d, %d)", k, k%parentRows) 108 k++ 109 } 110 r.Exec(b, fmt.Sprintf("INSERT INTO child VALUES %s", strings.Join(vals, ","))) 111 } 112 }) 113 }) 114 }