Comments 5
У вас результаты исходного и оптимизированного запросов отличаются. Исходный запрос сперва делает join, а потом sum, а второй сперва sum, а потом DISTINCT, из-за чего сумма в 8 раз больше. До:
i sum
1 288
2 288
3 288
После:
i sum
1 36
2 36
3 36
Совершенно верно, и это еще один повод проверять каждую гипотезу на фактических данных.
В реальных условиях при подобных модификациях запроса может (и наверняка будет) меняться агрегатная функция для получения совпадающего результата - например, sum превратится в count или возникнет необходимость добавить FILTER.
Из моей практики: проблемы обычно возникают со сложными аналитическими запросами, т.к. они пытаются собрать данные из кучи таблиц, что-то там просуммировать и все это с хорошей вложенностью, что путает планировщик, а еще требует кучи индексов по всем этим таблицам. Так вот для таких случаев в 99% работает способ денормализации бд: т.е. мы делаем отдельную таблицу в бд «удобную для этого запроса», куда, дублируя данные, пишем на операциях записи.
Первый метод сводится к правилу «не надо выбирать лишних данных», ну точнее очень близко к нему лежит по смыслу: «не надо соединяться с таблицей, из которой данные не нужны» — и его тоже мало шансов встретить на реальном проекте.
Вот как раз с попытками "сначала все приджойнить" в реальном проекте приходится сталкиваться очень часто - даже разбирал на примерах.
Мне кажется что все же сложные аналитические выборки лучше не в OLTP базе делать а в OLAP-кубе. И если вы уже как часть практики имеете денормализованные таблицы - наверное уже пповод подумать и подключить OLAP
PostgreSQL Antipatterns: делаем группировку быстрее от 0.1 до 5 раз