Ответ
Пакетная обработка запросов (batching) — это эффективный способ отправить несколько команд к базе данных за один сетевой вызов, что снижает задержки и повышает производительность.
В Go это можно реализовать с помощью драйверов, поддерживающих такую функциональность. Наиболее популярным и современным решением является pgx
.
Пример с использованием pgx
pgx
предоставляет удобный интерфейс pgx.Batch
для работы с пакетами запросов.
package main
import (
"context"
"fmt"
"os"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgxpool"
)
func main() {
ctx := context.Background()
// Убедитесь, что у вас есть доступ к БД
dbpool, err := pgxpool.New(ctx, os.Getenv("DATABASE_URL"))
if err != nil {
fmt.Fprintf(os.Stderr, "Unable to create connection pool: %vn", err)
os.Exit(1)
}
defer dbpool.Close()
batch := &pgx.Batch{}
// Добавляем запросы в очередь
batch.Queue("SELECT id, name FROM users WHERE id = $1", 1)
batch.Queue("SELECT id, price FROM products WHERE id = $1", 42)
// Отправляем пакет
results := dbpool.SendBatch(ctx, batch)
// Важно закрыть results, чтобы освободить соединение
defer results.Close()
// Читаем результаты в том же порядке, в котором отправляли запросы
var userID int
var userName string
if err := results.QueryRow().Scan(&userID, &userName); err != nil {
fmt.Fprintf(os.Stderr, "Failed to read user: %vn", err)
}
fmt.Printf("User: ID=%d, Name=%sn", userID, userName)
var productID int
var productPrice float64
if err := results.QueryRow().Scan(&productID, &productPrice); err != nil {
fmt.Fprintf(os.Stderr, "Failed to read product: %vn", err)
}
fmt.Printf("Product: ID=%d, Price=%.2fn", productID, productPrice)
}
Ключевые моменты:
- Порядок важен: Результаты нужно читать строго в том же порядке, в котором запросы были добавлены в
batch
. - Освобождение ресурсов: Всегда используйте
defer results.Close()
, чтобы гарантировать, что соединение с базой данных вернется в пул, даже если при обработке результатов произойдет паника. - Обработка ошибок: Проверяйте ошибку после каждого вызова
.Scan()
. Ошибка в одном из запросов не прерывает выполнение всего пакета, но результат для этого запроса будет содержать ошибку.