Найти в Дзене
Записки о Java

15 важнейших вопросов по базам данных для собеседования Java-разработчика

💡 Зачем спрашивают: чтобы понять, сталкивались ли вы с фантомными чтениями, грязными данными, неповторяющимися чтениями. Ответ: Java-пример (Spring Boot + @Transactional): @Transactional(isolation = Isolation.REPEATABLE_READ) public List<Order> getOrders(Long userId) { return orderRepository.findByUserId(userId); } Важно: не все СУБД поддерживают все уровни одинаково! В MySQL InnoDB REPEATABLE READ ближе к SERIALIZABLE. 💡 Зачем спрашивают: проверяют, понимаете ли вы стоимость операций DML. Ответ: Совет: всегда смотрите EXPLAIN ANALYZE в PostgreSQL! 💡 Зачем спрашивают: проверяют, умеете ли вы писать эффективный код с ORM. Ответ: @Query("SELECT u FROM User u JOIN FETCH u.orders WHERE u.id = :id") User findUserWithOrders(@Param("id") Long id); @EntityGraph(attributePaths = "orders") Optional<User> findById(Long id); ✅ Best practice: избегайте ленивой загрузки в web-слое — она почти всегда приводит к N+1. 💡 Зачем спрашивают: проверяют опыт работы с конкурентностью. Ответ: Java: ловите
Оглавление

1. Что такое уровни изоляции транзакций? Какие есть в PostgreSQL/MySQL? Чем отличается READ COMMITTED от REPEATABLE READ?

💡 Зачем спрашивают: чтобы понять, сталкивались ли вы с фантомными чтениями, грязными данными, неповторяющимися чтениями.

Ответ:

  • READ UNCOMMITTED — читает незафиксированные изменения (грязное чтение). В PostgreSQL не поддерживается.
  • READ COMMITTED (по умолчанию в PostgreSQL) — видны только зафиксированные данные. Но при повторном SELECT в рамках одной транзакции могут прийти новые строки (фантомные чтения).
  • REPEATABLE READ — гарантирует, что повторные SELECT вернут те же данные. В PostgreSQL реализован через MVCC, но не защищает от сериализуемых аномалий.
  • SERIALIZABLE — полная изоляция, но может вызывать конфликты сериализации.

Java-пример (Spring Boot + @Transactional):

@Transactional(isolation = Isolation.REPEATABLE_READ)

public List<Order> getOrders(Long userId) {

return orderRepository.findByUserId(userId);

}

Важно: не все СУБД поддерживают все уровни одинаково! В MySQL InnoDB REPEATABLE READ ближе к SERIALIZABLE.

2. Что такое индекс? Как он устроен? Когда он помогает, а когда вредит?

💡 Зачем спрашивают: проверяют, понимаете ли вы стоимость операций DML.

Ответ:

  • Индекс — структура данных (чаще всего B-Tree), которая ускоряет поиск по столбцу.
  • Помогает при WHERE, JOIN, ORDER BY.
  • Вредит при частых INSERT/UPDATE/DELETE — индекс нужно перестраивать.
  • Composite index (мультиколоночный) работает слева направо: (a, b, c) — эффективен для WHERE a = ? AND b = ?, но не для WHERE b = ?.

Совет: всегда смотрите EXPLAIN ANALYZE в PostgreSQL!

3. Что такое N+1 проблема? Как её решить в JPA/Hibernate?

💡 Зачем спрашивают: проверяют, умеете ли вы писать эффективный код с ORM.

Ответ:

  • Проблема: 1 запрос на родителя + N запросов на детей.
  • Решения:JOIN FETCH в JPQL:

@Query("SELECT u FROM User u JOIN FETCH u.orders WHERE u.id = :id")

User findUserWithOrders(@Param("id") Long id);

  • @EntityGraph

@EntityGraph(attributePaths = "orders")

Optional<User> findById(Long id);

Best practice: избегайте ленивой загрузки в web-слое — она почти всегда приводит к N+1.

4. Что такое deadlock? Как его избежать? Как обнаружить в PostgreSQL?

💡 Зачем спрашивают: проверяют опыт работы с конкурентностью.

Ответ:

  • Deadlock — циклическое ожидание ресурсов между двумя+ транзакциями.
  • Избежать:Блокировать ресурсы в одном порядке,
    Делать транзакции
    короткими,
    Использовать SELECT FOR UPDATE SKIP LOCKED (для очередей).
  • В PostgreSQL: смотреть логи (log_lock_waits = on) или использовать pg_stat_activity.

Java: ловите PersistenceException → проверяйте причину → retry-логика.

5. Чем VARCHAR(255) отличается от TEXT в PostgreSQL? Есть ли смысл ограничивать длину?

💡 Зачем спрашивают: проверяют знание внутреннего устройства СУБД.

Ответ (PostgreSQL-specific):

  • В PostgreSQL нет разницы в производительности между VARCHAR(n), VARCHAR, TEXT.
  • Все хранятся как varlena (переменная длина).
  • Ограничение длины (VARCHAR(50)) — это ограничение бизнес-логики, а не оптимизация.
  • Но: в других СУБД (MySQL, Oracle) разница есть!
Рекомендация: используйте TEXT + валидацию на уровне приложения (например, @Size(max = 255) в Bean Validation).

6. Как работает EXPLAIN? Что означают Seq Scan, Index Scan, Bitmap Heap Scan?

💡 Зачем спрашивают: проверяют, умеете ли вы читать план выполнения.

Ответ:

  • Seq Scan — полное сканирование таблицы (плохо при больших данных).
  • Index Scan — идёт по индексу, затем по таблице.
  • Bitmap Heap Scan — используется при множественных условиях: сначала строится bitmap из индексов, потом читаются строки.

Совет: если видите Seq Scan на большой таблице — скорее всего, нужен индекс.

7. Что такое CTE? Когда использовать WITH вместо подзапроса?

💡 Зачем спрашивают: проверяют знание современного SQL.

Ответ:

  • CTE (WITH) — временный именованный результат, улучшает читаемость.
  • В PostgreSQL рекурсивные CTE позволяют работать с иерархиями (например, деревья категорий).
  • Начиная с PostgreSQL 12, CTE не материализуются по умолчанию — оптимизатор может встроить их.

Пример (рекурсивный CTE для дерева):

WITH RECURSIVE tree AS (

SELECT id, parent_id, name FROM categories WHERE id = 1

UNION ALL

SELECT c.id, c.parent_id, c.name FROM categories c

JOIN tree t ON c.parent_id = t.id

)

SELECT * FROM tree;

8. Что такое connection pool? Почему нельзя создавать Connection вручную в Spring Boot?

💡 Зачем спрашивают: проверяют понимание производительности и ресурсов.

Ответ:

  • Создание соединения — дорогая операция (TCP handshake, аутентификация).
  • Connection pool (HikariCP в Spring Boot) переиспользует соединения.
  • Если создавать Connection вручную — вы быстро исчерпаете лимиты СУБД.

Java 11 + Spring Boot: Hikari настроен по умолчанию. Не трогайте DriverManager.getConnection()!

9. Что такое миграции БД? Почему нельзя менять схему вручную?

💡 Зачем спрашивают: проверяют зрелость в DevOps-практиках.

Ответ:

  • Миграции (Flyway, Liquibase) — версионирование схемы БД.
  • Позволяют:Воспроизводить окружение,
    Откатываться,
    Избегать “works on my machine”.
  • Никогда не меняйте схему вручную в продакшене!

10. Как выбрать между UUID и BIGINT в качестве первичного ключа?

💡 Зачем спрашивают: проверяют системное мышление.

Ответ:

Критерий

BIGINT (SEQUENCE)

UUID

Производительность

Выше (int сравнение)

Ниже (16 байт, фрагментация)

Распределённость

Требует центрального генератора

Можно генерить на клиенте

Безопасность

Угадываемый ID

Непредсказуемый

Размер

8 байт

16 байт

11. Что такое partial index? Приведите пример использования.

💡 Зачем спрашивают: проверяют знание продвинутых возможностей СУБД.

Ответ:

  • Partial index — индекс по подмножеству строк.
  • Экономит место и ускоряет поиск.

Пример (PostgreSQL):

-- Индекс только для активных пользователей

CREATE INDEX idx_users_active_email ON users(email) WHERE active = true;

✅ Используйте, когда часто фильтруете по одному значению флага.

12. Как работает MVCC в PostgreSQL? Почему SELECT не блокирует UPDATE?

💡 Зачем спрашивают: проверяют понимание архитектуры СУБД.

Ответ:

  • MVCC (Multi-Version Concurrency Control) — каждая транзакция видит снимок данных на момент старта.
  • UPDATE создаёт новую версию строки, старая остаётся для других транзакций.
  • Поэтому SELECT и UPDATE не блокируют друг друга (в большинстве случаев).
✅ Это причина, почему PostgreSQL масштабируется лучше, чем MySQL с MyISAM.

13. Что такое PreparedStatement? Почему нельзя использовать конкатенацию строк для SQL?

💡 Зачем спрашивают: проверяют базовую безопасность.

Ответ:

  • PreparedStatement — параметризованный запрос.
  • Защищает от SQL-инъекций.
  • Повышает производительность (план кэшируется).

Java 11 (правильно):

String sql = "SELECT * FROM users WHERE email = ?";

try (PreparedStatement stmt = conn.prepareStatement(sql)) {

stmt.setString(1, email);

// ...

}

Никогда так:

// ❌ УЯЗВИМОСТЬ!

String sql = "SELECT * FROM users WHERE email = '" + email + "'";

4. Когда использовать NoSQL (MongoDB), а когда SQL (PostgreSQL)?

💡 Зачем спрашивают: проверяют способность выбирать технологию под задачу.

Ответ:

  • SQL: строгая схема, транзакции, отношения, отчёты.
  • NoSQL: гибкая схема, горизонтальное масштабирование, документы.

Примеры:

  • Онлайн-кинотеатр (билеты, места, транзакции) → PostgreSQL.
  • Логи пользовательских событий → MongoDB.

5. Как вы обеспечиваете согласованность данных в распределённой системе?

💡 Зачем спрашивают: проверяют опыт в микросервисной архитектуре.

Ответ:

  • Saga pattern — последовательность локальных транзакций с компенсирующими действиями.
  • Outbox pattern — запись событий в ту же транзакцию, что и данные.
  • Eventual consistency — принятие того, что данные сойдутся со временем.