330 lines
7.4 KiB
Go
330 lines
7.4 KiB
Go
|
package benchmarks
|
|||
|
|
|||
|
import (
|
|||
|
"database/sql"
|
|||
|
"log"
|
|||
|
"testing"
|
|||
|
|
|||
|
_ "github.com/lib/pq"
|
|||
|
)
|
|||
|
|
|||
|
const (
|
|||
|
accountID = "64f2cd7a7047f28fdabf6d9e"
|
|||
|
connStr = "host=localhost port=35432 user=squiz password=Redalert2 dbname=squiz sslmode=disable"
|
|||
|
queryTotal = `
|
|||
|
WITH user_data AS (
|
|||
|
SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $1 AND accountsAmo.Deleted = false
|
|||
|
)
|
|||
|
SELECT f.*, COUNT(*) OVER() as total_count
|
|||
|
FROM fields f JOIN user_data u ON f.AccountID = u.AmoID
|
|||
|
WHERE f.Deleted = false
|
|||
|
ORDER BY f.ID OFFSET ($2 - 1) * $3 LIMIT $3;
|
|||
|
`
|
|||
|
queryCount = `
|
|||
|
WITH user_data AS (
|
|||
|
SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $1 AND accountsAmo.Deleted = false
|
|||
|
)
|
|||
|
SELECT COUNT(*)
|
|||
|
FROM fields f JOIN user_data u ON f.AccountID = u.AmoID
|
|||
|
WHERE f.Deleted = false;
|
|||
|
`
|
|||
|
queryData = `
|
|||
|
WITH user_data AS (
|
|||
|
SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $1 AND accountsAmo.Deleted = false
|
|||
|
)
|
|||
|
SELECT f.*
|
|||
|
FROM fields f JOIN user_data u ON f.AccountID = u.AmoID
|
|||
|
WHERE f.Deleted = false
|
|||
|
ORDER BY f.ID OFFSET ($2 - 1) * $3 LIMIT $3;
|
|||
|
`
|
|||
|
)
|
|||
|
|
|||
|
type GetFieldsWithPaginationRow struct {
|
|||
|
ID int64 `db:"id" json:"id"`
|
|||
|
Amoid int32 `db:"amoid" json:"amoid"`
|
|||
|
Code string `db:"code" json:"code"`
|
|||
|
Accountid int32 `db:"accountid" json:"accountid"`
|
|||
|
Name string `db:"name" json:"name"`
|
|||
|
Entity interface{} `db:"entity" json:"entity"`
|
|||
|
Type interface{} `db:"type" json:"type"`
|
|||
|
Deleted bool `db:"deleted" json:"deleted"`
|
|||
|
Createdat sql.NullTime `db:"createdat" json:"createdat"`
|
|||
|
TotalCount int64 `db:"total_count" json:"total_count"`
|
|||
|
}
|
|||
|
|
|||
|
func initDB() *sql.DB {
|
|||
|
db, err := sql.Open("postgres", connStr)
|
|||
|
if err != nil {
|
|||
|
log.Fatal(err)
|
|||
|
}
|
|||
|
return db
|
|||
|
}
|
|||
|
|
|||
|
// Все получаем в одном запросе не аллоцируя при этом массив
|
|||
|
func BenchmarkAllOne(b *testing.B) {
|
|||
|
db := initDB()
|
|||
|
defer db.Close()
|
|||
|
for i := 0; i < b.N; i++ {
|
|||
|
page := 1
|
|||
|
size := 25
|
|||
|
rows, err := db.Query(queryTotal, accountID, page, size)
|
|||
|
if err != nil {
|
|||
|
b.Fatal(err)
|
|||
|
}
|
|||
|
defer rows.Close()
|
|||
|
|
|||
|
var results []GetFieldsWithPaginationRow
|
|||
|
for rows.Next() {
|
|||
|
var row GetFieldsWithPaginationRow
|
|||
|
if err := rows.Scan(
|
|||
|
&row.ID,
|
|||
|
&row.Amoid,
|
|||
|
&row.Code,
|
|||
|
&row.Accountid,
|
|||
|
&row.Name,
|
|||
|
&row.Entity,
|
|||
|
&row.Type,
|
|||
|
&row.Deleted,
|
|||
|
&row.Createdat,
|
|||
|
&row.TotalCount,
|
|||
|
); err != nil {
|
|||
|
b.Fatal(err)
|
|||
|
}
|
|||
|
results = append(results, row)
|
|||
|
}
|
|||
|
|
|||
|
if err := rows.Err(); err != nil {
|
|||
|
b.Fatal(err)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Все получаем в одном запросе аллоцируя при этом массив
|
|||
|
func BenchmarkAllOnePreAllocation(b *testing.B) {
|
|||
|
db := initDB()
|
|||
|
defer db.Close()
|
|||
|
for i := 0; i < b.N; i++ {
|
|||
|
page := 1
|
|||
|
size := 25
|
|||
|
rows, err := db.Query(queryTotal, accountID, page, size)
|
|||
|
if err != nil {
|
|||
|
b.Fatal(err)
|
|||
|
}
|
|||
|
defer rows.Close()
|
|||
|
|
|||
|
results := make([]GetFieldsWithPaginationRow, size)
|
|||
|
for rows.Next() {
|
|||
|
var row GetFieldsWithPaginationRow
|
|||
|
if err := rows.Scan(
|
|||
|
&row.ID,
|
|||
|
&row.Amoid,
|
|||
|
&row.Code,
|
|||
|
&row.Accountid,
|
|||
|
&row.Name,
|
|||
|
&row.Entity,
|
|||
|
&row.Type,
|
|||
|
&row.Deleted,
|
|||
|
&row.Createdat,
|
|||
|
&row.TotalCount,
|
|||
|
); err != nil {
|
|||
|
b.Fatal(err)
|
|||
|
}
|
|||
|
results = append(results, row)
|
|||
|
}
|
|||
|
|
|||
|
if err := rows.Err(); err != nil {
|
|||
|
b.Fatal(err)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Считается сначала количество потом получаются данные длину и емкость массиву не меняем
|
|||
|
func BenchmarkCountThenGetData(b *testing.B) {
|
|||
|
db := initDB()
|
|||
|
defer db.Close()
|
|||
|
for i := 0; i < b.N; i++ {
|
|||
|
page := 1
|
|||
|
size := 25
|
|||
|
|
|||
|
row := db.QueryRow(queryCount, accountID)
|
|||
|
var totalCount int
|
|||
|
if err := row.Scan(&totalCount); err != nil {
|
|||
|
b.Fatal(err)
|
|||
|
}
|
|||
|
var results []GetFieldsWithPaginationRow
|
|||
|
rows, err := db.Query(queryData, accountID, page, size)
|
|||
|
if err != nil {
|
|||
|
b.Fatal(err)
|
|||
|
}
|
|||
|
defer rows.Close()
|
|||
|
|
|||
|
for rows.Next() {
|
|||
|
var row GetFieldsWithPaginationRow
|
|||
|
if err := rows.Scan(
|
|||
|
&row.ID,
|
|||
|
&row.Amoid,
|
|||
|
&row.Code,
|
|||
|
&row.Accountid,
|
|||
|
&row.Name,
|
|||
|
&row.Entity,
|
|||
|
&row.Type,
|
|||
|
&row.Deleted,
|
|||
|
&row.Createdat,
|
|||
|
); err != nil {
|
|||
|
b.Fatal(err)
|
|||
|
}
|
|||
|
results = append(results, row)
|
|||
|
}
|
|||
|
|
|||
|
if err := rows.Err(); err != nil {
|
|||
|
b.Fatal(err)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Параллельное вычисление данных и общего количество при этом длина слайса = size
|
|||
|
func BenchmarkParallel(b *testing.B) {
|
|||
|
db := initDB()
|
|||
|
defer db.Close()
|
|||
|
|
|||
|
for i := 0; i < b.N; i++ {
|
|||
|
page := 1
|
|||
|
size := 25
|
|||
|
results := make([]GetFieldsWithPaginationRow, size)
|
|||
|
channel := make(chan error, 2)
|
|||
|
|
|||
|
go func() {
|
|||
|
row := db.QueryRow(queryCount, accountID)
|
|||
|
var totalCount int
|
|||
|
channel <- row.Scan(&totalCount)
|
|||
|
}()
|
|||
|
|
|||
|
go func() {
|
|||
|
rows, err := db.Query(queryData, accountID, page, size)
|
|||
|
if err != nil {
|
|||
|
channel <- err
|
|||
|
return
|
|||
|
}
|
|||
|
defer rows.Close()
|
|||
|
|
|||
|
index := 0
|
|||
|
for rows.Next() {
|
|||
|
if err := rows.Scan(
|
|||
|
&results[index].ID,
|
|||
|
&results[index].Amoid,
|
|||
|
&results[index].Code,
|
|||
|
&results[index].Accountid,
|
|||
|
&results[index].Name,
|
|||
|
&results[index].Entity,
|
|||
|
&results[index].Type,
|
|||
|
&results[index].Deleted,
|
|||
|
&results[index].Createdat,
|
|||
|
); err != nil {
|
|||
|
channel <- err
|
|||
|
return
|
|||
|
}
|
|||
|
index++
|
|||
|
}
|
|||
|
channel <- rows.Err()
|
|||
|
}()
|
|||
|
|
|||
|
for i := 0; i < 2; i++ {
|
|||
|
if err := <-channel; err != nil {
|
|||
|
b.Fatal(err)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Считается сначала количество потом получаются данные создаем слайс через маке указывая ему длину начальную кап = лен
|
|||
|
func BenchmarkWithPreAllocation(b *testing.B) {
|
|||
|
db := initDB()
|
|||
|
defer db.Close()
|
|||
|
|
|||
|
for i := 0; i < b.N; i++ {
|
|||
|
page := 1
|
|||
|
size := 25
|
|||
|
results := make([]GetFieldsWithPaginationRow, size)
|
|||
|
|
|||
|
row := db.QueryRow(queryCount, accountID)
|
|||
|
var totalCount int
|
|||
|
if err := row.Scan(&totalCount); err != nil {
|
|||
|
b.Fatal(err)
|
|||
|
}
|
|||
|
rows, err := db.Query(queryData, accountID, page, size)
|
|||
|
if err != nil {
|
|||
|
b.Fatal(err)
|
|||
|
}
|
|||
|
defer rows.Close()
|
|||
|
|
|||
|
index := 0
|
|||
|
for rows.Next() {
|
|||
|
if err := rows.Scan(
|
|||
|
&results[index].ID,
|
|||
|
&results[index].Amoid,
|
|||
|
&results[index].Code,
|
|||
|
&results[index].Accountid,
|
|||
|
&results[index].Name,
|
|||
|
&results[index].Entity,
|
|||
|
&results[index].Type,
|
|||
|
&results[index].Deleted,
|
|||
|
&results[index].Createdat,
|
|||
|
); err != nil {
|
|||
|
b.Fatal(err)
|
|||
|
}
|
|||
|
index++
|
|||
|
}
|
|||
|
|
|||
|
if err := rows.Err(); err != nil {
|
|||
|
b.Fatal(err)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func BenchmarkWithPreAllocationAndMonitoringTotalCount(b *testing.B) {
|
|||
|
db := initDB()
|
|||
|
defer db.Close()
|
|||
|
|
|||
|
for i := 0; i < b.N; i++ {
|
|||
|
page := 1
|
|||
|
size := 50
|
|||
|
|
|||
|
row := db.QueryRow(queryCount, accountID)
|
|||
|
var totalCount int
|
|||
|
if err := row.Scan(&totalCount); err != nil {
|
|||
|
b.Fatal(err)
|
|||
|
}
|
|||
|
if totalCount < size {
|
|||
|
size = totalCount
|
|||
|
}
|
|||
|
results := make([]GetFieldsWithPaginationRow, size)
|
|||
|
rows, err := db.Query(queryData, accountID, page, size)
|
|||
|
if err != nil {
|
|||
|
b.Fatal(err)
|
|||
|
}
|
|||
|
defer rows.Close()
|
|||
|
|
|||
|
index := 0
|
|||
|
for rows.Next() {
|
|||
|
if err := rows.Scan(
|
|||
|
&results[index].ID,
|
|||
|
&results[index].Amoid,
|
|||
|
&results[index].Code,
|
|||
|
&results[index].Accountid,
|
|||
|
&results[index].Name,
|
|||
|
&results[index].Entity,
|
|||
|
&results[index].Type,
|
|||
|
&results[index].Deleted,
|
|||
|
&results[index].Createdat,
|
|||
|
); err != nil {
|
|||
|
b.Fatal(err)
|
|||
|
}
|
|||
|
index++
|
|||
|
}
|
|||
|
|
|||
|
if err := rows.Err(); err != nil {
|
|||
|
b.Fatal(err)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|