Что делать, если сложный запрос в базе данных долго выполняется?
Что проверяют
Есть ли у вас метод. Ответ «добавить индекс» без разбора причины считается слабым.
Как отвечать
По шагам.
1. Посмотреть план: EXPLAIN (ANALYZE, BUFFERS). Смотреть на узел с наибольшим временем, на расхождение оценки и факта (значит статистика устарела, помогает ANALYZE), на последовательный просмотр большой таблицы и на сортировки, ушедшие на диск.
2. Понять причину. Обычно одна из: нет подходящего индекса; индекс есть, но не применяется из-за функции над колонкой или несовпадения типов; выбирается слишком много строк, и планировщик прав; неудачный порядок соединений; работа с диском вместо памяти.
3. Исправить по возрастанию стоимости: переписать запрос (убрать лишние соединения, вынести условие, взять только нужные колонки), затем индекс (составной с правильным порядком, частичный, покрывающий), затем предподсчёт (материализованное представление, витрина), и только потом настройки и железо.
4. Проверить, что причина не в другом. Запрос может не выполняться, а ждать: блокировки, длинная транзакция рядом, исчерпанный пул соединений. Это видно в pg_stat_activity, а не в плане.
5. Замерить снова на боевом объёме данных, а не на десяти тестовых строках.
Отдельно: если приложение делает тысячу быстрых запросов вместо одного (N+1), оптимизировать каждый бессмысленно, надо менять выборку.
Где спотыкаются
Правят наугад, не открыв план.
Не различают «медленно выполняется» и «долго ждёт блокировку».
Забывают, что функция над колонкой отключает обычный индекс.
Меряют на пустой тестовой базе и удивляются, что в проде не помогло.