Я ищу создать функцию Postgres, который кэширует результаты длительных запросов, так что нужно только быть выполнена один раз за одну транзакцию:индекс Результаты Postgres таблицы Функция
CREATE OR REPLACE FUNCTION get_records (
_state VARCHAR(10)
)
RETURNS TABLE (
id UUID
) AS
$$
DECLARE
_temptable VARCHAR;
BEGIN
_temptable := FORMAT('temp_state_%s', _state);
IF NOT EXISTS(SELECT 1 FROM pg_tables WHERE tablename = _temptable) THEN
EXECUTE FORMAT('CREATE TEMPORARY TABLE %I (id UUID NOT NULL, PRIMARY KEY(_uid)) ON COMMIT DROP', _temptable);
EXECUTE FORMAT('INSERT INTO %I SELECT id FROM very_complex_nested_query', _temptable);
EXECUTE FORMAT('ANALYZE %I', _temptable);
END IF;
RETURN QUERY EXECUTE FORMAT('SELECT id FROM %I', _temptable);
END;
$$
LANGUAGE 'plpgsql';
Теперь я могу выполнять все мои запросы и присоединиться к этой функции:
SELECT mt.*
FROM my_table1 mt
INNER JOIN get_records('new') nr ON mt.id = nr.id
SELECT mt.*
FROM my_table2 mt
INNER JOIN get_records('new') nr ON mt.id = nr.id
SELECT mt.*
FROM my_table3 mt
INNER JOIN get_records('new') nr ON mt.id = nr.id
-- ... many more
У меня есть целая куча этих, без гарантий, по которым вы будете работать в первую очередь или в каком порядке.
Это работает очень хорошо, за исключением того, что индекс первичного ключа во временной таблице не используется.
Как я могу вернуть «таблицу» из функции Postgres, а не только результаты запроса?
- Я использую функцию, чтобы построить временную таблицу вместо материализованные представления, чтобы получить вокруг «where clause doesn't get pushed into view that contains aggregation» вопрос.
- Я мог бы создать временную таблицу, а затем обратиться к ней непосредственно во всех запросах, но это означало бы, что нужно создать какой-то механизм блокировки, чтобы гарантировать, что запросы не выполняются слишком рано, а инструмент, использование не очень хорошо поддерживает такие механизмы.
Не создавайте временную таблицу, не используйте временную таблицу. Не анализируйте таблицу temp. Поместите «very_complex_nested_query» в обычную функцию 'sql'. Запрос, использующий эту функцию sql, может быть оптимизирован намного лучше, чем черный ящик, который PL/pgSQL представляет оптимизатору. –
@a_horse_with_no_name Но ... «very_complex_nested_query» занимает 5 минут, и, поскольку я присоединяюсь к результатам к сотням отдельных запросов, я добавляю дни к общему времени выполнения. Разве это не точный пример временного стола? Что вы подразумеваете под «простой функцией sql»? –
Я имею в виду 'language sq' вместо' language plpgsql', но если вы хотите его индексировать, вам нужно создать индекс в таблице temp. –