Как вы работаете с большими и сложными SQL-запросами в Java?

«Как вы работаете с большими и сложными SQL-запросами в Java?» — вопрос из категории Базы данных, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Да, работал. Основные подходы включают использование PreparedStatement (JDBC) или JdbcTemplate (Spring) для безопасного выполнения запросов.

Пример с PreparedStatement:

String sql = """
    SELECT u.id, u.name, o.order_date, SUM(oi.price) as total
    FROM users u
    JOIN orders o ON u.id = o.user_id
    JOIN order_items oi ON o.id = oi.order_id
    WHERE u.status = ? AND o.created_at > ?
    GROUP BY u.id, u.name, o.order_date
    HAVING total > ?
    ORDER BY total DESC
    LIMIT 1000
    """;

try (PreparedStatement stmt = connection.prepareStatement(sql)) {
    stmt.setString(1, "ACTIVE");
    stmt.setDate(2, Date.valueOf("2024-01-01"));
    stmt.setBigDecimal(3, new BigDecimal("1000"));
    ResultSet rs = stmt.executeQuery();
    // Обработка результата
}

Ключевые практики оптимизации:

  • Анализ плана выполнения: Использование EXPLAIN ANALYZE для выявления узких мест.
  • Пагинация: Замена LIMIT/OFFSET на ключевой курсор (WHERE id > ? LIMIT N) для больших наборов данных.
  • Индексы: Создание составных индексов для полей в условиях WHERE, JOIN и ORDER BY.
  • Денормализация: Введение вычисляемых колонок или материализованных представлений для тяжелых агрегаций.
  • В ORM (Hibernate): Использование @NamedNativeQuery или EntityGraph для контроля N+1 проблемы и явного управления загрузкой данных.