Last active
December 4, 2023 09:45
-
-
Save twpayne/7da8892eed03d948464671a51949e7e9 to your computer and use it in GitHub Desktop.
CockroachDB bulk insert test case
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "bytes" | |
| "database/sql" | |
| "flag" | |
| "html/template" | |
| "strconv" | |
| "strings" | |
| "testing" | |
| "time" | |
| _ "github.com/lib/pq" | |
| "github.com/stretchr/testify/assert" | |
| "github.com/stretchr/testify/require" | |
| ) | |
| const ( | |
| // defaultDSN is the data source name for a CockroachDB instance running | |
| // locally, started with: | |
| // cockroach start --insecure --listen-addr=localhost | |
| // You will need to create the testdb database: | |
| // echo "CREATE DATABASE testdb;" | psql -h localhost -p 26257 -U root | |
| defaultDSN = "postgresql://root@localhost:26257/testdb?sslmode=disable" | |
| ) | |
| var ( | |
| dsn = flag.String("dsn", defaultDSN, "data source name") | |
| ) | |
| func TestCockroachDBBulkInsert(t *testing.T) { | |
| batchSize := 1000 | |
| numBatches := 10 | |
| valueSize := 16 * 1024 | |
| // Open the connection to the database. | |
| db, err := sql.Open("postgres", *dsn) | |
| require.NoError(t, err) | |
| defer db.Close() | |
| // Check the connection. | |
| require.NoError(t, db.Ping()) | |
| // Create a unique table name for this test. | |
| tableName := "test_pairs_" + strconv.Itoa(int(time.Now().UnixNano())) | |
| data := struct { | |
| TableName string | |
| BatchSize int | |
| }{ | |
| TableName: tableName, | |
| BatchSize: batchSize, | |
| } | |
| funcs := template.FuncMap{ | |
| "makeInsertValues": makeInsertValues, | |
| } | |
| // Create the table and ensure it is cleaned up afterwards. | |
| createTableQuery, err := executeTemplate("create_table_query", ` | |
| CREATE TABLE {{ .TableName }} ( | |
| key BYTEA PRIMARY KEY, | |
| value BYTEA NOT NULL | |
| ); | |
| `, data, nil) | |
| require.NoError(t, err) | |
| dropTableQuery, err := executeTemplate("drop_table_query", ` | |
| DROP TABLE {{ .TableName }}; | |
| `, data, nil) | |
| require.NoError(t, err) | |
| _, err = db.Exec(createTableQuery) | |
| require.NoError(t, err) | |
| defer func() { | |
| _, err := db.Exec(dropTableQuery) | |
| assert.NoError(t, err) | |
| }() | |
| // Create a bulk insert query. | |
| insertQuery, err := executeTemplate("insert_query", ` | |
| INSERT INTO {{ .TableName }} (key, value) | |
| VALUES {{ makeInsertValues 2 ", " .BatchSize ", "}} | |
| ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value; | |
| `, data, funcs) | |
| require.NoError(t, err) | |
| // Insert numBatches batches of batchSize pairs with unique keys and values of valueSize. | |
| value := make([]byte, valueSize) | |
| for i := 0; i < numBatches; i++ { | |
| args := make([]interface{}, 0, 2*batchSize) | |
| for j := 0; j < batchSize; j++ { | |
| key := []byte(strconv.Itoa(j)) | |
| args = append(args, key, value) | |
| } | |
| _, err := db.Exec(insertQuery, args...) | |
| require.NoError(t, err) | |
| } | |
| } | |
| func executeTemplate(name, text string, data interface{}, funcs template.FuncMap) (string, error) { | |
| t, err := template.New(name).Funcs(funcs).Parse(text) | |
| if err != nil { | |
| return "", err | |
| } | |
| b := &bytes.Buffer{} | |
| if err := t.Execute(b, data); err != nil { | |
| return "", err | |
| } | |
| return b.String(), nil | |
| } | |
| func makeInsertValues(cols int, colSep string, rows int, rowSep string) string { | |
| b := &strings.Builder{} | |
| for r := 0; r < rows; r++ { | |
| if r != 0 { | |
| b.WriteString(rowSep) | |
| } | |
| b.WriteByte('(') | |
| for c := 0; c < cols; c++ { | |
| if c != 0 { | |
| b.WriteString(colSep) | |
| } | |
| b.WriteByte('$') | |
| b.WriteString(strconv.Itoa(r*cols + c + 1)) | |
| } | |
| b.WriteByte(')') | |
| } | |
| return b.String() | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment