Index
Куратор раздела
Шустиков Владимир, оставивший военную жизнь позади и ушедший в данные с головой. Работаю с данными более 2х лет и останавливаться не собираюсь! Веду:
Если хочешь сменить текущую профессию на Дата Инженера — пиши не стесняйся, я сам проходил этот не легкий путь и тебе помогу https://t.me/ShustDE
Хочешь улучшить текущий раздел, внести недостающее или поправить формулировку? Предлагай PR и тегай @ShustGF.
Правила хорошего тона
1) Используйте только те колонки, которые вам необходимы. Не нужно в продовый запрос тыкать “SELECT *”, в 90% всех таблиц в ГП используется колоночное хранение(каждая колонка находится в отдельном файле), это в свою очередь ведет к поиску всех колонок.
2) Изучайте DDL таблиц перед тем как с ними работать. Обращайте внимание по какким полям таблица рапределена и партицирована. В фильтрах старайтесь указывать поля партицирования, чтобы уменьшить кол-во считываемых данных.
3) Чаще всего партиции строят на несколько месяцев-лет вперед, поэтому при фильтрации по дате партицирования обязательно ставте границу до сегодняшнего дня, в противном случае БД будет заходить в партиции, в которых нет данных.
where dt > '2025-05-01' and dt < current_timestamp()
where date between '2025-05-01' and current_date()
4) Не делайте бессмысленных преобразований типов данных.
where date_trunc('month', dt)::date < current_date -- здесь и так округление до 00:00:00
5) Не преобразуйте колонки, по которым парцированы или распредлены таблицы, это приведет к новому перераспределению данных, а парции вообще использоваться не будут
6) Из фильтрации убирайте функции, они там не нужны. Если необходимо фильтрануться по пользовательской функции, находите ее текст(посмотреть скрипт можно тут и используйте только те условия, которые вам нужны, либо расчет выводите в отдельную темповую таблицу.
7) Не соединяйте таблицы не по ключам распределения. Старайтесь выводить данные таблицы в темповые, фильтровать их по максисуму, распределять по логике ваших дальнейших соединений.
8) Используйте предрасчитанные поля, так как нужно заново высчитывать значения поля
where dt + interval '3h' > curremt_timestamp - interval '7 day' -- левая чать не предрасчитана
where dt > curremt_timestamp - interval '7 day' - interval '3h' -- левая чать предрасчитана
9) Усли условие JOIN большое(3 и более условий) например
from t1
JOIN t2
ON t1.col1 = t2.col1 and
t1.col2 = t2.col2 and
t1.col3 = t2.col3 and
t1.col4 = t2.col4
лучше вынесите таблицы в темповую таблицу, захешируйте значения(но обращаю внимание hash(null)
дает заначение, поэтому либо отфильтруйте их либо воспользуйтесь CASE) иначе соединится не то что нужно
11) group by
и partition by
делайте по полям дистрибуции
12) В GreenPlum нет наследование алиасов, не нужно копировать 10 преобразований одно и того же поля, выведите все в отдельное СТЕ и уже работайте от туда
13) В JOIN не указывайте поля соединения через OR, старайтесь уйти от этого
14) небольшие таблицы можно делать в дистрибуцией по Replicated это позволит быстрее обрабатывать JOIN в запросах
15) Не используйте plpgsql функций в теле запроса, это замендляет работу запроса
Кейсы
Кейс 1: Уходи от OR в JOIN'ах
Есть запрос в котором втречается JOIN с 3мя условиями. Таблицы имеют большое кол-во строк.
SELECT ...
FROM _tmp_calc_cred AS cc
INNER JOIN _postback_api as pa
ON cc.request_external_id = pa.EXTERNAL_ID OR
cc.calculation_id = pa.EXTERNAL_ID OR
cc.request_id = pa.EXTERNAL_ID
Во первых в данном случе стоит рапледелить таблицу _tmp_calc_cred
по всем сегментам, так как в JOIN используется 3 разные колонки, а таблицу _postback_api
по ключу EXTERNAL_ID
, чтобы запрос выполнялся параллельно на разных сегментах.
Данный запрос стоит преобразовать к следующиму виду:
select ...
FROM alexd._tmp_CALCULATION_CREDIT AS cc
INNER JOIN alexd._postback_api as pa
ON cc.request_external_id = pa.EXTERNAL_ID
union all
select ...
FROM alexd._tmp_CALCULATION_CREDIT AS cc
INNER JOIN alexd._postback_api as pa
ON cc.calculation_id = pa.EXTERNAL_ID
union
select ...
FROM alexd._tmp_CALCULATION_CREDIT AS cc
INNER JOIN alexd._postback_api as pa
ON cc.request_id = pa.EXTERNAL_ID
В первом случае выберится физический вид JOIN'а - Nested Loop
, 2й запрос хоть и больше, но выберится Hash JOIN
. Здесь главное по отдельности запустить запросы и пприкинуть, какое максимальное кол-во строк может получиться в результате. Если строк в результате получается больше, чем в самих таблицах (произошел CROSS JOIN данных), то возможно 1й вариант будет выстрее!