Что такое план выполнения запроса в базе данных
Что проверяют
Умеете ли вы объяснять медленный запрос инструментами базы, а не догадками. Для питониста добавляется второй слой: видите ли вы за объектной моделью реальный SQL и умеете ли достать план из приложения, а не только из консоли.
Как отвечать
План это дерево операций, которое планировщик выбрал для запроса: как достать строки (последовательное чтение, индексный проход, битовая карта), как соединить таблицы (вложенные циклы, хеш, слияние), где сортировка и агрегация. Выбор делает оптимизатор по статистике, то есть по оценкам числа строк и селективности, а не по красоте текста запроса.
В PostgreSQL команда EXPLAIN показывает план с оценками и запрос не выполняет. EXPLAIN с параметрами ANALYZE и BUFFERS выполняет запрос и показывает фактические строки, время и работу с буферами. Для изменяющих запросов такой замер делают внутри транзакции с откатом.
Что читать в первую очередь: расхождение оценки и факта, обычно это устаревшая статистика или зависимые условия; число строк, умноженное на количество проходов во вложенном цикле; сортировку, ушедшую на диск; чтение с диска против попаданий в кэш.
Из Python: у Django есть метод explain на выборке, в SQLAlchemy план берут, выполнив EXPLAIN для скомпилированного запроса, а на проде удобнее модуль автоматического журналирования планов медленных запросов. Анализировать надо тот SQL, который реально ушёл в базу, с параметрами.
Где спотыкаются
Читают стоимость как миллисекунды. Это безразмерные единицы планировщика, сравнивать их осмысленно только между планами одного запроса, а реальное время показывает лишь фактический прогон.
Считают последовательное чтение приговором и вешают индекс на каждый столбец. На небольшой таблице и при выборке заметной доли строк такое чтение дешевле индексного, а лишние индексы замедляют запись. Отдельная ловушка это функция или приведение типа над столбцом в условии: подходящий индекс есть, но применён не будет.
Снимают план на копии с сотней строк и переносят вывод на боевые объёмы. Второй типичный промах при работе с объектной моделью: у каждого запроса план прекрасный, но страница делает их сотнями, и план одного запроса эту проблему не покажет вовсе.