0
0
mirror of https://gitlab.com/cznic/sqlite.git synced 2025-04-27 23:07:44 +00:00
Files
go-sqlite/benchmark/bench.go

377 lines
9.2 KiB
Go

// Copyright 2021 The Sqlite Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package benchmark
/*
this file contains benchmarks inspired by https://www.sqlite.org/speed.html
*/
import (
"database/sql"
"fmt"
"math/rand"
"testing"
)
// corresponds to Test 1 from https://www.sqlite.org/speed.html
func benchInsert(b *testing.B, db *sql.DB) {
// create test table
createTestTable(db)
// measure from here
b.ResetTimer()
fillTestTable(db, b.N)
}
// corresponds to Test 2 from https://www.sqlite.org/speed.html
func benchInsertInTransaction(b *testing.B, db *sql.DB) {
// create test table
createTestTable(db)
// measure from here
b.ResetTimer()
fillTestTableInTx(db, b.N)
}
// corresponds to Test 3 from https://www.sqlite.org/speed.html
func benchInsertIntoIndexed(b *testing.B, db *sql.DB) {
// create test table with indexed column
createTestTable(db, `c`)
b.ResetTimer()
fillTestTableInTx(db, b.N)
}
// corresponds to Test 4 from https://www.sqlite.org/speed.html
func benchSelectWithoutIndex(b *testing.B, db *sql.DB) {
// create test table
createTestTable(db)
// fill test table
fillTestTableInTx(db, testTableRowCount)
// prepare statement for selection
stmt, err := db.Prepare(fmt.Sprintf(`SELECT count(*), avg(b) FROM %s WHERE b>=? AND b<?`, testTableName))
if err != nil {
panic(err)
}
defer stmt.Close()
b.ResetTimer()
runInTransaction(db, func() {
// exec many selects
// SELECT count(*), avg(b) FROM t2 WHERE b>=0 AND b<1000;
// SELECT count(*), avg(b) FROM t2 WHERE b>=100 AND b<1100;
// SELECT count(*), avg(b) FROM t2 WHERE b>=200 AND b<1200;
// ...
for i := 0; i < b.N; i++ {
b := (i * 100) % maxGeneratedNum
if _, err := stmt.Exec(b, b+1000); err != nil {
panic(err)
}
}
})
}
// corresponds to Test 5 from https://www.sqlite.org/speed.html
func benchSelectOnStringComparison(b *testing.B, db *sql.DB) {
// create test table
createTestTable(db)
// fill test table
fillTestTableInTx(db, testTableRowCount)
// prepare statement for selection
stmt, err := db.Prepare(fmt.Sprintf(`SELECT count(*), avg(b) FROM %s WHERE c LIKE ?`, testTableName))
if err != nil {
panic(err)
}
defer stmt.Close()
b.ResetTimer()
runInTransaction(db, func() {
// exec many selects
// SELECT count(*), avg(b) FROM t2 WHERE c LIKE '%one%';
// SELECT count(*), avg(b) FROM t2 WHERE c LIKE '%two%';
// ...
// SELECT count(*), avg(b) FROM t2 WHERE c LIKE '%ninety nine%';
for i := 1; i <= b.N; i++ {
// e.g. following will produce "... WHERE c LIKE '%seventy eight%' "
likeCond := pronounceNum(uint32(i) % 100)
if _, err := stmt.Exec(`%` + likeCond + `%`); err != nil {
panic(err)
}
}
})
}
// corresponds to Test 6 from https://www.sqlite.org/speed.html
func benchCreateIndex(b *testing.B, db *sql.DB) {
// create test table
createTestTable(db)
// fill test table
fillTestTableInTx(db, testTableRowCount)
var (
nameIdxA = "iA"
nameIdxB = "iB"
createIndStmtA = fmt.Sprintf(`CREATE INDEX %s ON %s(a)`, nameIdxA, testTableName)
createIndStmtB = fmt.Sprintf(`CREATE INDEX %s ON %s(c)`, nameIdxB, testTableName)
dropIndStmtA = fmt.Sprintf(`DROP INDEX IF EXISTS %s`, nameIdxA)
dropIndStmtB = fmt.Sprintf(`DROP INDEX IF EXISTS %s`, nameIdxB)
)
b.ResetTimer()
for i := 1; i <= b.N; i++ {
// drop indexes from previous iteration (if any)
b.StopTimer()
mustExec(db, dropIndStmtA, dropIndStmtB)
b.StartTimer()
// create indexes
runInTransaction(db, func() {
mustExec(db, createIndStmtA, createIndStmtB)
})
}
}
// corresponds to Test 7 from https://www.sqlite.org/speed.html
func benchSelectWithIndex(b *testing.B, db *sql.DB) {
// create test table with indexed field
createTestTable(db, `b`)
// fill test table
fillTestTableInTx(db, testTableRowCount)
// prepare statement for selection
stmt, err := db.Prepare(fmt.Sprintf(`SELECT count(*), avg(b) FROM %s WHERE b>=? AND b<?`, testTableName))
if err != nil {
panic(err)
}
defer stmt.Close()
b.ResetTimer()
runInTransaction(db, func() {
// exec many selects
// SELECT count(*), avg(b) FROM t2 WHERE b>=0 AND b<100;
// SELECT count(*), avg(b) FROM t2 WHERE b>=100 AND b<200;
// SELECT count(*), avg(b) FROM t2 WHERE b>=200 AND b<300;
for i := 0; i < b.N; i++ {
b := (i * 100) % maxGeneratedNum
if _, err := stmt.Exec(b, b+100); err != nil {
panic(err)
}
}
})
}
// corresponds to Test 8 from https://www.sqlite.org/speed.html
func benchUpdateWithoutIndex(b *testing.B, db *sql.DB) {
// create test table
createTestTable(db)
// fill test table
fillTestTableInTx(db, testTableRowCount)
// prepare statement
stmt, err := db.Prepare(fmt.Sprintf(`UPDATE %s SET b=b*2 WHERE a>=? AND a<?`, testTableName))
if err != nil {
panic(err)
}
defer stmt.Close()
b.ResetTimer()
runInTransaction(db, func() {
// exec many
// UPDATE t1 SET b=b*2 WHERE a>=0 AND a<10;
// UPDATE t1 SET b=b*2 WHERE a>=10 AND a<20;
// UPDATE t1 SET b=b*2 WHERE a>=20 AND a<30;
for i := 0; i < b.N; i++ {
a := (i * 10) % testTableRowCount
if _, err := stmt.Exec(a, a+10); err != nil {
panic(err)
}
}
})
}
// corresponds to Test 9 from https://www.sqlite.org/speed.html
func benchUpdateWithIndex(b *testing.B, db *sql.DB) {
// create test table
createTestTable(db, `a`)
// fill test table
fillTestTableInTx(db, testTableRowCount)
// prepare statement
stmt, err := db.Prepare(fmt.Sprintf(`UPDATE %s SET b=? WHERE a=?`, testTableName))
if err != nil {
panic(err)
}
defer stmt.Close()
b.ResetTimer()
runInTransaction(db, func() {
// exec many
// UPDATE t2 SET b=468026 WHERE a=1;
// UPDATE t2 SET b=121928 WHERE a=2;
// ...
for i := 0; i < b.N; i++ {
if _, err := stmt.Exec(
rand.Uint32(), // b = ?
i%testTableRowCount+1, // WHERE a=?
); err != nil {
panic(err)
}
}
})
}
// corresponds to Test 10 from https://www.sqlite.org/speed.html
func benchUpdateTextWithIndex(b *testing.B, db *sql.DB) {
// create test table
createTestTable(db, `a`)
// fill test table
fillTestTableInTx(db, testTableRowCount)
// prepare statement
stmt, err := db.Prepare(fmt.Sprintf(`UPDATE %s SET c=? WHERE a=?`, testTableName))
if err != nil {
panic(err)
}
defer stmt.Close()
b.ResetTimer()
runInTransaction(db, func() {
// exec many
// UPDATE t2 SET c='one hundred forty eight thousand three hundred eighty two' WHERE a=1;
// UPDATE t2 SET c='three hundred sixty six thousand five hundred two' WHERE a=2;
for i := 0; i < b.N; i++ {
// generate new random number-as-words for c
if _, err := stmt.Exec(
pronounceNum(uint32(rand.Int31n(maxGeneratedNum))), // SET c=?
i%testTableRowCount+1, // WHERE a=?
); err != nil {
panic(err)
}
}
})
}
// corresponds to Test 11 from https://www.sqlite.org/speed.html
func benchInsertFromSelect(b *testing.B, db *sql.DB) {
// create source table
createTestTable(db)
fillTestTableInTx(db, testTableRowCount)
// create name for target table
targetTableName := fmt.Sprintf("%s_copy", testTableName)
// need to create table here, otherwise prepared statement will give error
createTestTableWithName(db, targetTableName)
// prepare statement
stmt, err := db.Prepare(fmt.Sprintf(`INSERT INTO %s SELECT b,a,c FROM %s`, targetTableName, testTableName))
if err != nil {
panic(err)
}
defer stmt.Close()
b.ResetTimer()
for i := 0; i < b.N; i++ {
// drop/create target table
b.StopTimer()
createTestTableWithName(db, targetTableName)
b.StartTimer()
runInTransaction(db, func() {
if _, err := stmt.Exec(); err != nil {
panic(err)
}
})
}
}
// corresponds to Test 12 from https://www.sqlite.org/speed.html
func benchDeleteWithoutIndex(b *testing.B, db *sql.DB) {
// create test table
createTestTable(db)
// prepare statement for deletion
stmt, err := db.Prepare(fmt.Sprintf(`DELETE FROM %s WHERE c LIKE '%%fifty%%'`, testTableName))
if err != nil {
panic(err)
}
defer stmt.Close()
b.ResetTimer()
for i := 0; i < b.N; i++ {
// drop/create target table
b.StopTimer()
fillTestTableInTx(db, testTableRowCount)
b.StartTimer()
runInTransaction(db, func() {
if _, err := stmt.Exec(); err != nil {
panic(err)
}
})
}
}
// corresponds to Test 13 from https://www.sqlite.org/speed.html
func benchDeleteWithIndex(b *testing.B, db *sql.DB) {
// create test table with indexed column
createTestTable(db, `a`)
// prepare statement for BIG deletion (nearly half of table rows)
stmt, err := db.Prepare(fmt.Sprintf(`DELETE FROM %s WHERE a>%d AND a<%d`, testTableName, 10, testTableRowCount/2))
if err != nil {
panic(err)
}
defer stmt.Close()
b.ResetTimer()
for i := 0; i < b.N; i++ {
// drop/create target table
b.StopTimer()
fillTestTableInTx(db, testTableRowCount)
b.StartTimer()
runInTransaction(db, func() {
if _, err := stmt.Exec(); err != nil {
panic(err)
}
})
}
}
// corresponds to Test 16 from https://www.sqlite.org/speed.html
func benchDropTable(b *testing.B, db *sql.DB) {
for i := 0; i < b.N; i++ {
b.StopTimer()
createTestTable(db)
fillTestTableInTx(db, testTableRowCount)
b.StartTimer()
if _, err := db.Exec(fmt.Sprintf("DROP TABLE %s", testTableName)); err != nil {
panic(err)
}
}
}