← Назад к вопросам

Что делал с реляционными БД

1.2 Junior🔥 251 комментариев
#Soft Skills и карьера

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

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

Релякционные базы данных - это основа большинства enterprise приложений, и я имею обширный опыт работы с ними. Рассмотрю ключевые аспекты моей работы.

1. SQL запросы и оптимизация

Я регулярно писал сложные SQL запросы с JOIN'ами, GROUP BY, подзапросами и оконными функциями.

// Получить топ 10 пользователей по количеству заказов за последний месяц
String query = """
    SELECT u.id, u.name, COUNT(o.id) as order_count
    FROM users u
    LEFT JOIN orders o ON u.id = o.user_id
    WHERE o.created_at >= DATE_SUB(NOW(), INTERVAL 1 MONTH)
    GROUP BY u.id, u.name
    HAVING COUNT(o.id) > 0
    ORDER BY order_count DESC
    LIMIT 10
""";

Основные навыки:

  • Написание сложных JOIN запросов
  • Использование индексов для оптимизации
  • EXPLAIN анализ для профилирования
  • Работа с выборкой больших объемов данных через пагинацию

2. ORM технологии (Hibernate/JPA)

Я использовал Hibernate и JPA для маппирования объектов на таблицы БД.

@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "email", unique = true, nullable = false)
    private String email;

    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Order> orders = new ArrayList<>();

    @ManyToOne
    @JoinColumn(name = "company_id")
    private Company company;
}

@Entity
@Table(name = "orders")
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    @JoinColumn(name = "user_id", nullable = false)
    private User user;

    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
    private List<OrderItem> items = new ArrayList<>();
}

3. Миграции данных

Я использовал Flyway и Liquibase для управления схемой БД через версионирование.

-- V1__Create_users_table.sql
CREATE TABLE users (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    email VARCHAR(255) NOT NULL UNIQUE,
    name VARCHAR(255) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX idx_users_email ON users(email);

-- V2__Add_phone_to_users.sql
ALTER TABLE users ADD COLUMN phone VARCHAR(20);

Это позволяет:

  • Отслеживать все изменения схемы
  • Откатываться на предыдущие версии при необходимости
  • Синхронизировать БД между разработкой, тестированием и production

4. Transaction management

Я работал с ACID свойствами транзакций и управлением их жизненным циклом.

@Service
public class PaymentService {
    @Transactional
    public PaymentResult processPayment(Payment payment) {
        // Сохраняем платеж
        Payment savedPayment = paymentRepository.save(payment);
        
        // Обновляем баланс пользователя
        User user = userRepository.findById(payment.getUserId())
            .orElseThrow(UserNotFoundException::new);
        user.setBalance(user.getBalance().subtract(payment.getAmount()));
        userRepository.save(user);
        
        // Создаем лог операции
        auditLogRepository.save(new AuditLog(payment.getUserId(), "PAYMENT_PROCESSED"));
        
        return new PaymentResult(savedPayment.getId(), PaymentStatus.SUCCESS);
    }
}

Если происходит ошибка на любом этапе, вся транзакция откатится.

5. Connection pooling

Я конфигурировал HikariCP для оптимального использования соединений.

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mydb
    username: root
    password: secret
    hikari:
      maximum-pool-size: 20
      minimum-idle: 5
      connection-timeout: 30000
      idle-timeout: 600000
      max-lifetime: 1800000

Это предотвращает:

  • Истощение соединений
  • Слишком частное создание новых соединений
  • Утечки соединений

6. Многозначные отношения

Я работал с различными типами связей между таблицами.

// Один ко многим
@Entity
public class Company {
    @OneToMany(mappedBy = "company", cascade = CascadeType.ALL)
    private List<User> employees;
}

// Многие ко многим
@Entity
public class User {
    @ManyToMany
    @JoinTable(
        name = "user_roles",
        joinColumns = @JoinColumn(name = "user_id"),
        inverseJoinColumns = @JoinColumn(name = "role_id")
    )
    private Set<Role> roles;
}

7. Обработка больших объемов данных

Для обработки миллионов записей использовал batching и streaming.

@Service
public class DataProcessingService {
    public void processBulkData() {
        int batchSize = 1000;
        List<User> batch = new ArrayList<>();
        
        userRepository.findAllStream().forEach(user -> {
            user.setProcessed(true);
            batch.add(user);
            
            if (batch.size() == batchSize) {
                userRepository.saveAll(batch);
                batch.clear();
            }
        });
        
        if (!batch.isEmpty()) {
            userRepository.saveAll(batch);
        }
    }
}

8. Query optimization и N+1 problem

Я умею выявлять и решать проблемы с производительностью.

// Плохо: N+1 problem
List<User> users = userRepository.findAll();
for (User user : users) {
    System.out.println(user.getOrders().size()); // +1 query на каждого пользователя!
}

// Хорошо: Eager loading
@Query("SELECT u FROM User u LEFT JOIN FETCH u.orders")
List<User> findAllWithOrders();

// Или использование @EntityGraph
@EntityGraph(attributePaths = "orders")
List<User> findAll();

9. Денормализация и кэширование

Для часто используемых данных применял кэширование и денормализацию.

@Entity
public class UserSummary {
    private Long userId;
    private Integer totalOrders;  // Денормализованное поле
    private BigDecimal totalSpent;
}

@Service
public class UserService {
    @Cacheable(value = "users", key = "#id")
    public User findUser(Long id) {
        return userRepository.findById(id);
    }
}

Резюме

Мой опыт с реляционными БД включает:

  • Проектирование и нормализацию схем
  • Написание и оптимизацию SQL запросов
  • Использование ORM (Hibernate/JPA)
  • Управление транзакциями и ACID свойствами
  • Миграции данных (Flyway/Liquibase)
  • Оптимизацию производительности и индексирование
  • Работа с большими объемами данных
  • Конфигурирование connection pooling

Этот опыт позволяет мне писать эффективный и надежный код для работы с базами данных.