PostgreSQL Common Table Expressions против временной таблицы?

11

Документация PostgreSQL по WITH показывает следующий пример:

WITH regional_sales AS (
        SELECT region, SUM(amount) AS total_sales
        FROM orders
        GROUP BY region
     ), top_regions AS (
        SELECT region
        FROM regional_sales
        WHERE total_sales > (SELECT SUM(total_sales)/10 FROM regional_sales)
     )
SELECT region,
       product,
       SUM(quantity) AS product_units,
       SUM(amount) AS product_sales
FROM orders
WHERE region IN (SELECT region FROM top_regions)
GROUP BY region, product;

Он также отмечает:

Полезным свойством запросов WITH является то, что они оцениваются только один раз за выполнение родительского запроса, даже если на них ссылается более одного раза родительский запрос или один и тот же запрос WITH.

Я вижу, что это WITHможет быть использовано для других целей, таких как рекурсивная оценка. Но в приведенном выше примере, есть ли важное различие между использованием WITHи созданием временных таблиц?

Натан Лонг
источник
Когда вы используете CTE для построения запроса, добавление еще одного столбца в SELECTin WITHпросто вводит имя и перезапускается. Хотя с временной таблицей это заняло бы DROPи CREATE. С другой стороны, если вы строите запрос и собираетесь многократно использовать статические данные - создание временной таблицы с индексами определенно выгодно для CTE.
Вао Цун
@VaoTsun, если использовать TEMPORARY TABLEс ON COMMIT DROPвнутри запроса, это также вопрос модификации запроса и повторного запуска, верно? postgresql.org/docs/9.6/static/sql-createtable.html
Натан Лонг,

Ответы:

16

Есть несколько тонких различий, но ничего радикального:

  • Вы можете добавить индексы на временную таблицу;
  • Временные таблицы существуют в течение всего сеанса (или, если ON COMMIT DROPтранзакция), когда WITHобласть всегда строго ограничена запросом;
  • Если запрос вызывает функцию / процедуру, она может видеть временную таблицу, но он может не видеть никаких WITHтаблиц-выражений;
  • Временная таблица генерирует VACUUMработу с системными каталогами, которая WITHэтого не делает, для ее создания / заполнения требуется дополнительная обратная передача, а также требуется дополнительная работа по управлению кэшем сервера, поэтому она немного менее эффективна.

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

Однако другой вариант, подзапрос в FROMпредложении, имеет совсем другой набор преимуществ. В частности, он может быть встроенным, а квалификаторы могут быть перемещены вверх / вниз. Я написал об этом в недавней статье в блоге .

Крейг Рингер
источник
А как насчет просмотров и временных просмотров?
CMCDragonkai
1
В некотором роде, но ближе к временной таблице, чем термин CTE. Нет индексов. Сессия определена. Видно для функций / процедур. Нужен каталог пылесос.
Крейг Рингер