Ответ
JSONB — это бинарный формат для хранения JSON-данных в базах данных, в первую очередь в PostgreSQL. В отличие от текстового типа JSON
, JSONB
хранит данные в оптимизированном двоичном виде.
Ключевые особенности и преимущества JSONB:
- Производительность: Запросы к данным в формате
JSONB
выполняются значительно быстрее, так как данные не требуют парсинга при каждом чтении. Однако вставка данных происходит немного медленнее из-за необходимости преобразования текста в бинарный формат. - Индексация:
JSONB
поддерживает полноценную индексацию (например, с помощью GIN-индексов), что позволяет эффективно искать значения внутри JSON-документов. - Эффективность: Удаляются незначащие пробелы и порядок ключей не сохраняется. Также
JSONB
сохраняет только последнее значение для дублирующихся ключей.
Сравнение JSON и JSONB
Характеристика | JSON | JSONB |
---|---|---|
Хранение | Как есть, в текстовом виде | Оптимизированный бинарный формат |
Производительность | Медленнее при обработке и запросах | Быстрее при обработке и запросах |
Пробелы и порядок | Сохраняются | Не сохраняются |
Индексация | Ограниченная | Полная поддержка (GIN, GIN(jsonb_path_ops)) |
Вставка | Быстрее (нет конвертации) | Медленнее (требуется конвертация) |
Пример работы с JSONB в Go (с pgx
)
Для работы с JSONB
в Go удобно использовать тип json.RawMessage
, чтобы отложить парсинг данных до момента, когда это действительно необходимо.
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"os"
"github.com/jackc/pgx/v5"
)
// Структура для данных внутри JSON
type UserData struct {
Username string `json:"username"`
Roles []string `json:"roles"`
}
// Структура для строки из таблицы
type User struct {
ID int `json:"id"`
Data json.RawMessage `json:"data" // Поле для JSONB
}
func main() {
// ... подключение к БД ...
conn, err := pgx.Connect(context.Background(), os.Getenv("DATABASE_URL"))
if err != nil {
log.Fatal(err)
}
defer conn.Close(context.Background())
var user User
// Пример запроса к таблице users, где есть колонка data типа JSONB
err = conn.QueryRow(context.Background(), "SELECT id, data FROM users WHERE id = $1", 1).Scan(&user.ID, &user.Data)
if err != nil {
log.Fatal(err)
}
// Теперь можно распарсить JSONB-данные в нужную структуру
var userData UserData
if err := json.Unmarshal(user.Data, &userData); err != nil {
log.Fatal(err)
}
fmt.Printf("User ID: %d, Username: %s, Roles: %vn", user.ID, userData.Username, userData.Roles)
}