Кэшируются ли подзапросы PostgreSQL / CTE? - PullRequest
0 голосов
/ 18 сентября 2018

Под кэшированием я подразумеваю, есть ли вызов подзапроса для каждой выбранной строки?

Несколько примеров

-- Simple query
SELECT * FROM (
    SELECT * FROM accounts
) AS subquery;

-- Subquery with function
SELECT * FROM (
    SELECT AVG(id_groups) FROM accounts
) AS subquery;

-- More messy queries
SELECT * FROM (
  SELECT id_groups, AVG(id_accounts) OVER (PARTITION BY id_groups)
  FROM accounts
) AS subquery
GROUP BY subquery.id_groups, subquery.avg;

И более того

Есть ли разница между

SELECT * FROM (
    SELECT * FROM accounts
) AS subquery;

А

WITH everything_about_accounts AS (
    SELECT * FROM accounts
)
SELECT * FROM everything_about_accounts;

1 Ответ

0 голосов
/ 18 сентября 2018

О подзапросах в предложении FROM:

Подзапрос будет не выполняться для каждой возвращаемой строки; это не имело бы смысла в этих случаях.

В трех представленных вами случаях PostgreSQL даже сгладит подзапрос: оптимизатор понимает, что подзапрос не нужен, и соответствующим образом преобразует запросы.

Используйте EXPLAIN со своими запросами, чтобы увидеть это в действии.

О CTE:

В отличие от подзапросов в предложении FROM, CTE выступает в качестве барьера оптимизации , то есть оптимизатор не пытается сгладить его или выдвинуть в него условия.

Скорее, выполняется CTE и материализуется результат , а запрос выполняет сканирование CTE материализованного результата.

Опять же, используйте EXPLAIN, чтобы увидеть его в действии.

В сообществе PostgreSQL предпринимаются попытки снять ограничение (или функцию, потому что это способ управления оптимизатором), что CTE всегда материализуются.

...