Похоже, что худшая производительность происходит в JOIN (согласно запросу в вашем ответе, а не в вашем вопросе).В идеале вы не будете присоединяться к подзапросу, когда он дает много результатов, но я не понимаю, как вы можете избежать этого, учитывая ваши критерии.
Так вот мое предложение:
- Результаты подзапроса помещаются в временную таблицу
- Временная таблица индексируется
- Объединениевыполняется на временную таблицу
- Инкапсулируйте все это в функцию
Теперь я вообще ненавижу это делать, поскольку мне не нравится создавать временные таблицы, но иногда это действительно дает вамлучшая производительность для чего-то, что не может быть сделано другим способом.(Не сказать, что это не может быть сделано по-другому, но я не могу придумать более эффективный способ.)
Так что-то вроде этого:
CREATE OR REPLACE FUNCTION schema.my_function()
RETURNS TABLE (tb SOMETYPE, avg NUMERIC) AS
$BODY$
BEGIN
CREATE TEMP TABLE fm ON COMMIT DROP AS
select time_bucket('5 minutes', ts) as five_min,
avg(value) as value,
stddev(value) as stddev_value
from schema.table
where some_criteria = 42
and ts >= '2018-11-12 00:00:00'
and ts < '2018-11-13 00:00:00'
group by five_min;
CREATE INDEX ON fm (five_min);
RETURN time_bucket('5 minutes', ts), avg(value)
from schema.table
left join fm
on ts >= fm.five_min
and ts < fm.five_min + interval '5 minutes'
where some_criteria = 42
and ts >= '2018-11-12 00:00:00'
and ts < '2018-11-13 00:00:00'
and abs((value-avg_value)/stddev_value) < 1
group by tb;
END
$BODY$
LANGUAGE plpgsql;
Очевидно, индекс, который я создалпросто основан на примере в запросе, который вы разместили, хотя я вижу, что фактический запрос содержит другие вещи, так что вы хотите проиндексировать любые поля, к которым присоединяются.
Я назвал тип tb SOMETYPE, потому что я нене знаю, какой тип возвращает time_bucket.И, конечно, вы можете передавать любые части запроса, которые должны быть переменными, в качестве параметров.