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  }