EXPLAIN и оптимизация: вопросы для собеседования (часть 2)
EXPLAIN показывает план выполнения запроса и помогает понять, где теряется производительность. На собеседованиях спрашивают про индексы, Seq Scan vs Index Scan, стоимость JOIN-ов и как переписать медленный запрос. Этот навык отличает аналитика, который просто пишет SQL, от того, кто понимает, как база данных его выполняет.
Вопросы 6–10 из 20
6На большой таблице `events` запрос `SELECT * FROM events ORDER BY created_at DESC LIMIT 100` неожиданно работает быстро. Какое объяснение наиболее вероятно при наличии индекса по `created_at`?
A`LIMIT 100` отключает сортировку, поэтому `ORDER BY` не влияет.
B`ORDER BY` в таких запросах игнорируется оптимизатором.
CПланировщик всегда использует хэширование, когда есть `LIMIT`.
DПлан может сделать `Index Scan` по индексу на `created_at` и взять первые строки без шага `Sort`.
Ответ: `ORDER BY` + `LIMIT` часто ускоряется индексом по полю сортировки.
Если есть подходящий индекс по `created_at`, планировщик может читать строки уже в нужном порядке и остановиться после `LIMIT 100`. Тогда дорогая операция `Sort` не нужна или становится значительно дешевле. Поэтому одинаковый запрос без индекса может быть на порядки медленнее.
7В плане `EXPLAIN` для запроса по пользователю вы видите `Index Scan using orders_user_id_idx on orders`. Какой вывод наиболее корректен?
AПланировщик будет искать строки по ключу в индексе, не читая всю таблицу `orders` подряд.
B`Index Scan` гарантирует, что запрос всегда будет самым быстрым возможным.
C`Index Scan` означает, что результат уже отсортирован по любому столбцу.
DЭто означает, что база создала временную таблицу и читает её.
Ответ: `Index Scan` использует индекс, чтобы быстрее найти подходящие строки.
При `Index Scan` база сначала проходит по индексу (например, по `user_id`), а затем читает нужные строки таблицы. Это особенно выгодно, когда условие `WHERE` выбирает малую долю данных. Но даже при наличии `Index Scan` реальная скорость зависит от объёма возвращаемых строк и дисковых чтений.
8В выводе `EXPLAIN` вы видите узел `Seq Scan on orders`. Что это обычно означает?
AБаза использует индекс и читает только подходящие строки.
BБаза возвращает результат из кэша и не читает таблицу.
CБаза читает таблицу `orders` целиком и затем применяет `Filter` (условия `WHERE`).
DБаза блокирует таблицу `orders` до конца запроса.
Ответ: `Seq Scan` — последовательное чтение таблицы целиком.
При `Seq Scan` планировщик ожидает, что проще пройтись по всем строкам, чем прыгать по индексу. Это может быть нормальным для маленьких таблиц или когда условие `WHERE` отбирает большую долю данных. Узкое место возникает, когда таблица большая, а фильтр должен был сильно сузить выборку.
9В выводе `EXPLAIN` вы видите оценку `cost=0.00..431.00`. Какой вывод аналитик может сделать безопасно?
A`cost` — это точное время выполнения в миллисекундах.
B`cost` — это точное количество строк, которое вернет запрос.
C`cost` — относительная оценка планировщика, полезная для сравнения альтернативных планов, но не обещание реального времени.
D`cost` показывает объём памяти, который запрос выделит.
Ответ: Числа `cost` — это оценки планировщика, а не секунды.
В Postgres-подобных СУБД `cost` используется планировщиком, чтобы выбрать один план из нескольких. Значения можно использовать, чтобы прикинуть «дороже/дешевле» на одной и той же базе и при схожих условиях. Но переводить `cost` в секунды и обещать точное время выполнения по `EXPLAIN` нельзя.
10В `EXPLAIN` вы видите два последовательных шага: `Seq Scan` с `cost=0.00..120000.00` и затем `Aggregate` с `cost=120000.00..120500.00`. С чего логичнее начать поиск узкого места?
AС шага с самой большой «стоимостью» и объёмом данных (здесь `Seq Scan`), потому что он кормит все остальные узлы.
BС верхней строки плана, потому что она выполняется первой.
CС любого шага, где встречается слово `Aggregate`, потому что агрегаты всегда самые дорогие.
DС названия индекса: если индекса нет в плане, значит всё безнадёжно.
Ответ: Ищите тяжёлые узлы по `cost`/`rows` и помните, что «нижние» шаги кормят «верхние».
Обычно имеет смысл смотреть на узлы, которые читают/генерируют много строк (часто сканы и сортировки). Если «внизу» много работы, то «наверху» это не исправить. `cost` — не время, но он помогает быстро понять, где планировщик ожидает основные затраты.
Хотите тренировать интерактивно?
В приложении — таймер, прогресс, стрики и 1700+ вопросов по всем темам.
Тренировать в Telegram