Так же, как и вчера, я покажу 10 случайных правил из моей обширной полутора тысячной коллекции :)
Несколько заметок о производительности
1) count(DISTINCT unique)
Когда разработчик хочет посчитать количество уникальных значений, он скорее всего использует конструкцию count(DISTINCT).
Но если колонка, по которому требуется сделать выборку, является уникальным в силу уже имеющихся ограничений (уникальная колонка, результат работы функции в подзапросе и тд), то убрав DISTINCT в этом выражении, мы ускорим count в 100 раз.
2) Проверка на NULL значений после приведения типов
A IS NOT NULLв 2 раза быстрее чем
A :: type IS NOT NULL
Причем тайпкаст может быть прийти из подзапроса и обнаружить это будет не так просто.
Если такая конструкция используется в массовых операциях при сканировании таблицы, то довольно просто можно ускорить запросы просто убрав приведение типов.
Как понимаете, такие запросы довольно просто получить при использовании различных ORM.
3) В условии JOIN ON не используется присоединяемая таблица
Довольно популярная ошибка, которую так же можно отнести и в разряд архитектурных. Встречается повсеместно при копипасте:
... t1 JOIN t2 ON t1.id = t.id
Это приведет к лавинообразному росту: для каждой строки, где t1.id = t.id будут присоединяться ВСЕ данные из таблицы t2.
При аналитических запросах, где используются агрегационные функции довольно просто такое не заметить
4) JOIN таблиц без использования внешних ключей
JOIN t2 ON t1.id = t2.id
Если не существует внешнего ключа, описывающего связь t1.id и t2.id, то вполне возможно, что в запрос закралась ошибка, полученная при копипасте.
Эту проблему надо рассматривать вместе еще с одной DDL-проблемой: если есть внешний ключ, то исходящее поле стоит включить в индекс, т.к. по внешнему ключу скорее всего будет JOIN.
Целевая таблица внешнего ключа обязана иметь уникальный индекс, а в исходящей стоит создать обычный
JOIN по полям, не имеющих связи в виде внешнего ключа могут и не иметь подходящих индексов, что замедлит операцию.
Но эта ошибка выглядит более страшно с точки зрения архитектуры. Такой запрос вернет невалидный результат! Мы связали поля, которые не имеют логической связи.
5) порядок колонок в GROUP BY _МОЖЕТ_ иметь значение
Порядок колонок в группировке никак не влияет на содержимое результата. Но на производительность может влиять существенно. Результат _МОЖЕТ_ зависеть от кучи вещей:
вариативность данных, колонка или выражение используется в группировке, версия базы, включена ли JIT компиляция, и еще кучи параметров.
Попробуйте поменять порядок колонок в GROUP BY и возможно, вам удастся ускорить запрос в несколько раз
Но в bigquery, говорят, все пошло еще дальше, и там рекомендуют самостоятельно заниматься расстановкой условий в WHERE:
2.3 WHERE clause: Expression order matters
https://wklytech.medium.com/bigquery-sql-optimization-c7a7db170c56
Я все еще очень надеюсь, что это fake news :)