При обработке всей таблицы индексы, как правило, бесполезны (с возможным исключением сканирования только по индексу, если строки таблицы намного шире индекса).
И при обработке всей таблицы я не надеваюНе вижу много места для оптимизации производительности самого запроса.Одна незначительная вещь:
SELECT d.the_date
, <b>generate_series(d.the_date - last_observed
, d.the_date - first_observed) AS days_to_date</b>
, round(avg(price)) AS price
, area_id
FROM table_example
, (SELECT date '2019-01-19') AS d(the_date)
GROUP BY days_to_date, area_id;
Предполагая, что first_observed
& last_observed
равны date NOT NULL
и всегда < date '2019-01-19'
.Иначе вам нужно разыграть / сделать больше.
Таким образом, у вас есть только два вычитания, а затем generate_series()
работает с целыми числами (быстрее всего).
Добавленный мини-подзапрос просто для удобства, чтобы предоставить дату только один раз.В подготовленном операторе или функции вы можете использовать параметр, и он вам не нужен:
, (SELECT date '2019-01-19') AS d(the_date)
Кроме этого, если EXPLAIN (ANALYZE, BUFFERS)
упоминает «Диск» (пример: Sort Method: external merge Disk: 3240kB
), то(временное) более высокое значение для work_mem
должно помочь.См .:
Если вы не можете позволить себе больше оперативной памяти, а этапы агрегирования и / или сортировки по-прежнему перетекают на диск, это может помочь разделить и победить с помощью запроса, например, с помощью LATERAL
объединения:
SELECT d.the_date, f.*, a.area_id
FROM area a
, (SELECT date '2019-01-19') AS d(the_date)
, LATERAL (
SELECT generate_series(d.the_date - last_observed
, d.the_date - first_observed) AS days_to_date
, round(avg(price)) AS price
FROM table_example
WHERE area_id = a.area_id
GROUP BY 1
) f;
Принимая таблицу area
, очевидно.