Опишите ваш опыт работы с реляционными базами данных.

Ответ

Основной опыт я имею с PostgreSQL, также работал с MySQL и SQLite.

В контексте PostgreSQL я занимался:

  • Проектированием схем данных и нормализацией.
  • Написанием сложных SQL-запросов с использованием JOIN, GROUP BY, оконных функций и CTE (Common Table Expressions).
  • Оптимизацией производительности: анализом планов запросов (EXPLAIN ANALYZE), созданием и использованием различных типов индексов (B-Tree, GIN, GiST).
  • Работой с транзакциями и уровнями изоляции для обеспечения целостности данных (ACID).

Пример работы с транзакцией в Go с использованием database/sql:

package main

import (
    "database/sql"
    "log"

    _ "github.com/lib/pq" // Драйвер для PostgreSQL
)

func main() {
    db, err := sql.Open("postgres", "user=test dbname=test sslmode=disable")
    if err != nil {
        log.Fatal("Ошибка подключения к БД:", err)
    }
    defer db.Close()

    // Начало транзакции
    tx, err := db.Begin()
    if err != nil {
        log.Fatal("Ошибка начала транзакции:", err)
    }

    // Выполняем операции внутри транзакции
    _, err = tx.Exec("INSERT INTO users(name, email) VALUES($1, $2)", "Alice", "alice@example.com")
    if err != nil {
        // Если одна из операций не удалась, откатываем все изменения
        tx.Rollback()
        log.Println("Транзакция отменена:", err)
        return
    }

    // Если все успешно, подтверждаем изменения
    err = tx.Commit()
    if err != nil {
        log.Fatal("Ошибка подтверждения транзакции:", err)
    }

    log.Println("Транзакция успешно завершена!")
}

Также имею опыт работы со смежными инструментами: ORM GORM для быстрой разработки и системами миграций, такими как goose и migrate, для управления версиями схемы БД.

Ответ 18+ 🔞

А, ну так, про базы данных, да? Ну слушай, в основном я с PostgreSQL вожусь, как с родной, блядь. Ну и по мелочи, там, MySQL с SQLite тоже через руки проходили, куда без них.

С этой самой PostgreSQL я чего только не делал, ёпта:

  • Эту всю схему данных проектировал, нормализовал там всё, чтоб не дублировалось, как говно по стенке.
  • Запросы писал, блядь, такие, что сам потом полдня разбирался, что нахуярил: с JOIN, GROUP BY, оконными функциями и CTE (Common Table Expressions), ну, в общем, весь этот цирк.
  • Оптимизировал, сука, чтобы не тормозило. Сидел, в планы запросов (EXPLAIN ANALYZE) пялился, индексы разные (B-Tree, GIN, GiST) накручивал, как ёлочные игрушки.
  • С транзакциями и их уровнями изоляции работал, чтобы данные целыми были, эта самая ACID-ность, блядь. Чтобы не вышло, что деньги списались, а товар не пришёл, ядрёна вошь.

Вот, смотри, как в Go транзакцию обычно делают, на примере database/sql:

package main

import (
    "database/sql"
    "log"

    _ "github.com/lib/pq" // Драйвер для PostgreSQL
)

func main() {
    db, err := sql.Open("postgres", "user=test dbname=test sslmode=disable")
    if err != nil {
        log.Fatal("Ошибка подключения к БД:", err)
    }
    defer db.Close()

    // Начало транзакции
    tx, err := db.Begin()
    if err != nil {
        log.Fatal("Ошибка начала транзакции:", err)
    }

    // Выполняем операции внутри транзакции
    _, err = tx.Exec("INSERT INTO users(name, email) VALUES($1, $2)", "Alice", "alice@example.com")
    if err != nil {
        // Если одна из операций не удалась, откатываем все изменения
        tx.Rollback()
        log.Println("Транзакция отменена:", err)
        return
    }

    // Если все успешно, подтверждаем изменения
    err = tx.Commit()
    if err != nil {
        log.Fatal("Ошибка подтверждения транзакции:", err)
    }

    log.Println("Транзакция успешно завершена!")
}

А ещё, блядь, для скорости иногда ORM GORM юзал, чтобы не расписывать каждый чих. И миграциями вертел, через goose или migrate, чтобы схему базы не вручную обновлять, а как цивилизованные люди. В общем, не просто так кнопки нажимал.