Раньше у нас был действительно плохо работающий CTE, для выполнения которого требовалось 3-5 минут. Я изменил CTE и использовал функцию с временными таблицами для выполнения sh той же задачи. Теперь новая функция выполняется менее чем за 5 секунд.
Это то, что я сделал:
С
WITH CTE1 AS (
SELECT ...
FROM ...
),
CTE2 AS (
SELECT ...
FROM ...
),
CTEn AS (
SELECT ...
FROM ...
)
SELECT A,B,C,D
FROM CTE1
JOIN CTE2 ON ...
JOIN CTEn ON ...;
TO
CREATE OR REPLACE FUNCTION FUNC_ABC(a integer)
RETURNS TABLE(A integer, B integer, C integer, D integer)
LANGUAGE plpgsql
AS $function$
DECLARE
x ALIAS for $1;
BEGIN
DROP TABLE IF EXISTS CTE1;
DROP TABLE IF EXISTS CTE2;
DROP TABLE IF EXISTS CTEn;
CREATE TEMP TABLE CTE1 AS
( SELECT ...
FROM ...
);
CREATE TEMP TABLE CTE2 AS
( SELECT ...
FROM ...);
CREATE TEMP TABLE CTEn AS
( SELECT ...
FROM ...);
CREATE INDEX ix_cte1 ON CTE1(A);
CREATE INDEX ix_cte2 ON CTE2(B);
CREATE INDEX ix_cten ON CTEn(C);
CREATE INDEX ix_cten ON CTEn(D);
RETURNS QUERY SELECT A,B,C,D
FROM CTE1
JOIN CTE2 ON ...
JOIN CTEn ON ...
END;
$function$
;
As Я сказал выше, функция довольно быстро. Причина добавления «DROP TABLE» заключается в том, что в транзакции эта функция может выполняться любое количество раз. Но периодически мы видим ошибку вроде:
ERROR: must be owner of relation CTE1
Я не могу воспроизвести эту ошибку. И есть только один пользователь, который запускает эту функцию. Ни у какого другого пользователя нет прав на выполнение этой функции.
Я не мог придумать сценарий, когда это не удастся. Любые мысли о понимании будут оценены.