SELECT count(*) FROM (SELECT DISTINCT a ...)заметно ускоряет запросы, если:
- "a" является строковым полем (VARCHAR/TEXT)
- в качестве параметра count() выступает ROW только из строковых полей -
SELECT COUNT(DISTINCT (a,b))Если на текстовое поле, по которому делается DISTINCT нет индекса, то
SELECT count(*) FROM (SELECT DISTINCT a ...)будет МЕДЛЕННЕЕ, чем
SELECT count(DISTINCT a), но
SELECT COUNT(*) FROM (SELECT a FROM t GROUP BY a)будет быстрее.
Причем в индексе нужное поле должно стоять на 1 месте, иначе результат будет аналогичен запросу без индекса.
Если в качестве параметра count() выступает ROW из полей не только строковых типов, то результат также будет аналогичен запросу по текстовому полю без индекса.
Как было озвучено ранее, GROUP BY всегда быстрее DISTINCT. Поэтому, если есть выбор что использовать - используйте GROUP BY.
Для полей других типов (числовые, дата и время) такая "оптимизация" даст отрицательный эффект.
Стоит сгенерировать пруфы для разных типов, collation и прочего, но это все потом...
В зависимости от окружения, количества данных, насильно выключенного seq_scan и других параметров порядок разницы между результатами изменяется. Иногда он не выглядит столь драматично, чтобы стоило об этом переживать. Но все равно результаты укладываются в описанную выше схему.
Какие выводы мы можем сделать из этой истории?
- мы знаем намного меньше, чем нам кажется
- когда копируешь что-то с SO - проверяй на своих кейсах
- не все можно сказать только по самому запросу, многое зависит от типов
- используй статический анализ везде, где сможешь
- линтеры тоже используй, но четко осознавай границы применимости
Итак, сколько времени занимает создание правила для статического анализатора?
Одно правило можно писать несколько дней. Может так выйти, что данных, которые выдает наш парсер недостаточно для реализации некоторых правил. Тогда дорабатывается анализатор. Последний раз такая доработка заняла несколько месяцев.
Я как-нибудь вам обязательно расскажу как понять какие индексы PostgreSQL сможет использовать при выполнении запроса. Это очень интересно....