Как ускорить агрегацию на стороне сервера по многораздельной таблице - PullRequest
1 голос
/ 03 апреля 2019

Справочная информация

Я генерирую графики Tukey "Ящик с усами" из нормализованной многораздельной таблицы в Postgres 10.6 на RDS с 3 * 10 ^ 9 строками.

Я началпутем последовательного использования нескольких представлений, состоящих из этапа агрегации и последующего этапа обнаружения выбросов.Сначала на этапе агрегации я вычисляю медиану, 25%, 75%, IQR, (25% - 1,5 * IQR) нижний усик и (75% + 1,5 * IQR) верхний усик.Во-вторых, на этапе обнаружения выброса я выполняю поиск в таблице значений, которые находятся за пределами усов.

Агрегирование

create view aggregation as
select
    a.a_name,
    b.b_name,
    c.c_name,
    percentile_cont(0.5) within group (order by d.D) as median,
    etc for 75%, IQR, whiskers
from dtable as d
join atable as a on a.a_id = d.a_id
join etable as e on e.e_id = d.e_id
join ftable as f on f.f_id = e.f_id
join btable as b on b.b_id = f.b_id
join ctable as c on c.c_id = b.c_id
where (d.e_id between 3440500 and 3459500)
and (c.c_name = 'this_c_in_particular')
and (b.b_name in ('first_b', 'second_b', 'third_b'))
group by
a.a_name,
b.b_name,
c.c_name
;

Обратите внимание, что dtable разделен на e_id

Обнаружение выбросов

create view outliers as
select d.*
from dtable as d
join atable, etable, ftable, btable, ctable
join aggregation as agg on
    agg.a_name = atable.a_name,
    agg.b_name = btable.b_name,
    agg.c_name = ctable.c_name
where d.value < agg.lower_whisker or d.value > agg.upper_whisker
;

Результаты

В настоящее время, используя плоский клиентский фрейм данных pandas, я могу выполнить эти агрегации менее чем за 10 секунд после передачи по сети и на стороне сервера.понижающий.Однако на стороне клиента для выполнения этих агрегаций требуется не менее 1 минуты.

(EXPLAIN ANALYZE) plan доступен здесь: https://explain.depesz.com/s/0gAu

Вопрос

  1. Существует ли стандартный метод для быстрого расчета этих агрегаций?
  2. Есть ли способ заставить Postgres вычислять эти вещи параллельно, 1 работник на группу?

Любое понимание или обсуждение приветствуются - спасибо за чтение.

1 Ответ

2 голосов
/ 03 апреля 2019

В плане выполнения есть некоторые вещи, которые я не понимаю:

  • Почему существует узел Gather, если параллельные рабочие не планировались?От loops я бы ожидал двух рабочих.

  • Почему expain.depesz.com не считает 895693 итераций нижнего узла (возможно, это так же запутано приведенным выше, какДа)?

Тем не менее, некоторые проблемы могут быть обнаружены сразу:

  • Есть ужасные неверные оценки (725 вместо 895693 фактическихряды!).

  • Большую часть времени вы проводите в том виде, в котором он выплескивается на диск.

Итак, вот что вы можете улучшить безпереписав запрос:

  • Увеличивайте work_mem, пока сортировка не станет quicksort memory.Это должно быть наибольшим выигрышем.

    Вам не нужно увеличивать его глобально, вы можете запустить что-то вроде:

    BEGIN;
    SET LOCAL work_mem = '1GB';
    SELECT /* your query */;
    COMMIT;
    
  • Некоторые таблицы кажутсяимеют несвежую статистику.Попробуйте ANALYZE все таблицы, о которых идет речь, возможно, это принесет пользу.

  • Вероятно, вы можете соскоблить еще несколько секунд, избегая неуместных соединений вложенных циклов.Возможно, ANALYZE позаботится об этом.

    В качестве последнего средства вы можете просто отключить вложенные циклы для этого запроса, установив enable_nestloop = off для одного запроса с тем же трюком, который я показал для work_mem выше.

Сканирование секционированной таблицы не является вашей проблемой, поэтому вам не нужно беспокоиться о ее распараллеливании (PostgreSQL v11 стал умнее с этим).

Если все вышеперечисленное не делает запрос достаточно быстрым, вы можете рассмотреть возможность использования материализованного представления .Затем вы получаете немного устаревшие данные, но быстро.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...