Базы данных и SQL: вопросы на собеседовании

Нормализация, JOIN, индексы, транзакции и уровни изоляции, оконные функции, диагностика медленных запросов.

#1Проектированиеjunior

Что такое нормализация? Объясните первые три нормальные формы.

Нормализация — приведение схемы к виду, исключающему избыточность и аномалии вставки, обновления и удаления.

1НФ. Все значения атомарны: никаких списков в одной ячейке, нет повторяющихся групп колонок (phone1, phone2, phone3). У таблицы есть ключ.

2НФ. 1НФ плюс: каждый неключевой атрибут зависит от всего составного ключа, а не от его части. Актуально только при составном ключе. Пример нарушения: в таблице (заказ_id, товар_id, количество, название_товара) название зависит только от товар_id — его нужно вынести.

3НФ. 2НФ плюс: нет транзитивных зависимостей неключевых атрибутов друг от друга. Пример нарушения: в таблице студентов есть группа_id и название_группы — второе зависит от первого, а не от студента.

Что сказать дальше, чтобы отличиться: нормализация уменьшает дублирование, но увеличивает число JOIN-ов. В аналитических хранилищах сознательно денормализуют (схема «звезда»), потому что чтение важнее целостности записи. Знать, когда нормализацию нарушают намеренно, ценнее, чем помнить определения.

  • Что такое НФБК?
  • Когда денормализация оправдана?
#2SQLjunior

Какие бывают JOIN-ы и чем они различаются?

  • INNER JOIN — только строки, для которых нашлось совпадение в обеих таблицах.
  • LEFT JOIN — все строки левой таблицы; там, где справа совпадения нет, будут NULL.
  • RIGHT JOIN — зеркально.
  • FULL OUTER JOIN — все строки обеих таблиц.
  • CROSS JOIN — декартово произведение, n × m строк.
  • SELF JOIN — таблица соединяется сама с собой (иерархия сотрудник — руководитель).

Ловушка, которую проверяют чаще всего: условие на правую таблицу в WHERE превращает LEFT JOIN в INNER JOIN, потому что NULL не проходит фильтр. Такое условие должно быть в ON:

-- Неверно: отсеет клиентов без заказов
SELECT c.name, o.total FROM clients c
LEFT JOIN orders o ON o.client_id = c.id
WHERE o.created_at > '2026-01-01';

-- Верно
SELECT c.name, o.total FROM clients c
LEFT JOIN orders o ON o.client_id = c.id AND o.created_at > '2026-01-01';

Вторая типичная ошибка — «дублирование» строк при JOIN по связи один-ко-многим; агрегаты после такого JOIN считаются неверно.

  • Как найти строки, которых нет во второй таблице?
  • Чем EXISTS отличается от IN?
#3Индексыmiddle

Как работают индексы? Почему индекс может не использоваться?

Индекс — дополнительная структура (обычно B+-дерево), хранящая отсортированные значения колонки и ссылки на строки. Поиск по индексу — O(log n) вместо полного сканирования O(n).

Цена: каждый индекс замедляет INSERT, UPDATE, DELETE и занимает место. Индексировать всё подряд — типичная ошибка джуна.

Почему индекс игнорируется:

  1. Функция над колонкой: WHERE YEAR(created_at) = 2026 не использует индекс по created_at. Нужно WHERE created_at >= '2026-01-01' AND created_at < '2027-01-01' или функциональный индекс.
  2. Неявное приведение типов — сравнение строковой колонки с числом.
  3. `LIKE '%текст%'` с ведущим % — префиксный поиск невозможен.
  4. Низкая селективность: если условию удовлетворяет заметная часть таблицы, планировщику дешевле прочитать её целиком.
  5. Нарушен порядок колонок составного индекса. Индекс (a, b) работает для условий по a и по a, b, но не для одного b — правило «левого префикса».
  6. Устаревшая статистика — помогает ANALYZE.

Проверяется всё это командой EXPLAIN ANALYZE.

  • Что такое покрывающий индекс?
  • Чем кластерный индекс отличается от некластерного?
#4Транзакцииmiddle

Что такое ACID? Раскройте каждое свойство.

A — Atomicity (атомарность). Транзакция выполняется целиком либо не выполняется вовсе. Реализуется журналом отмены (undo log).

C — Consistency (согласованность). Транзакция переводит БД из одного корректного состояния в другое: соблюдаются ограничения, внешние ключи, триггеры. Это свойство обеспечивается совместно схемой и приложением.

I — Isolation (изолированность). Параллельные транзакции не видят промежуточных результатов друг друга. Степень изоляции регулируется уровнями — это компромисс между строгостью и производительностью.

D — Durability (долговечность). После подтверждения данные переживут отключение питания. Реализуется журналом упреждающей записи (WAL): сначала запись в журнал на диск, потом изменение страниц данных.

Классический пример: перевод денег между счетами. Списание и зачисление должны быть атомарны, иначе деньги исчезнут. Именно поэтому финансовые системы живут на реляционных БД с полноценными транзакциями.

Следующий вопрос обычно — про BASE и теорему CAP в распределённых системах.

  • Что такое WAL и зачем он нужен?
  • Чем BASE отличается от ACID?
#5Транзакцииmiddle

Назовите уровни изоляции транзакций и аномалии, которые они предотвращают.

Три классические аномалии:

  • Грязное чтение — читаем неподтверждённые изменения чужой транзакции.
  • Неповторяющееся чтение — перечитали ту же строку и получили другое значение.
  • Фантомное чтение — повторный запрос по условию вернул новый набор строк.
УровеньГрязноеНеповторяющеесяФантомы
READ UNCOMMITTEDвозможновозможновозможно
READ COMMITTEDнетвозможновозможно
REPEATABLE READнетнетвозможно*
SERIALIZABLEнетнетнет

\* В PostgreSQL REPEATABLE READ реализован через снимки (MVCC) и фантомов не допускает; в MySQL InnoDB их предотвращают gap-блокировки.

По умолчанию: PostgreSQL и Oracle — READ COMMITTED, MySQL InnoDB — REPEATABLE READ.

Чем строже уровень, тем больше блокировок и откатов при конфликтах. SERIALIZABLE в реальных системах включают точечно — для операций, где важна инвариантность (списание баланса, бронирование последнего места).

  • Как работает MVCC?
  • Что такое аномалия потерянного обновления?

Ещё 9 вопросов в этом треке

  1. В каком порядке выполняется SQL-запрос? Почему нельзя использовать алиас из SELECT в WHERE?
  2. Напишите запрос: вторая по величине зарплата в каждом отделе.
  3. Как ведёт себя NULL в SQL? Какие ошибки с ним допускают?
  4. Когда выбирать SQL, а когда NoSQL?
  5. Что такое проблема N+1 запроса и как её решать?
  6. Чем первичный ключ отличается от уникального индекса и внешнего ключа?
  7. Что такое SQL-инъекция и как от неё защититься?
  8. Запрос стал медленным. Опишите порядок диагностики.
  9. Чем репликация отличается от шардирования?