DISTINCT ON часто недооценивают, но в PostgreSQL это один из самых быстрых способов выбрать «последнюю запись на группу» без подзапросов и оконных функций.
Проблема
Нужно получить, например, последнюю запись по каждому user_id, отсортированную по created_at.
Типичное (медленное) решение
- оконная функция ROW_NUMBER()
- подзапрос с GROUP BY + JOIN
Редкое и очень быстрое решение
DISTINCT ON + индекс, совпадающий с ORDER BY.
Пример
Получаем последнюю сессию каждого пользователя.
SELECT DISTINCT ON (user_id)
user_id,
session_id,
created_at
FROM user_sessions
ORDER BY user_id, created_at DESC;
Почему это быстро
PostgreSQL берет первую строку на каждую группу user_id согласно ORDER BY и сразу останавливается - без сортировки всего результата и без оконных функций.
Ключевой момент оптимизации
Нужен правильный индекс, иначе магия не сработает.
CREATE INDEX idx_user_sessions_distinct
ON user_sessions (user_id, created_at DESC);
Что дает такой индекс
- Index Scan вместо Seq Scan
- Нет дополнительной сортировки
- Очень быстрый выбор «последней записи на группу» даже на миллионах строк
Где особенно полезно
- логины пользователей
- события
- статусы
- версии сущностей
- time-series данные
DISTINCT ON - это PostgreSQL-специфичная оптимизация, но если ты работаешь с Postgres, это один из самых мощных и редких трюков.