commit: 608b167f9f9c4553c35bb1ec0eab9ddae643989bauthor: Tom Lanedate: Sat, 16 Feb 2019 16:11:12 -0500Allow user control of CTE materialization, and change the default behavior.Historically we haveve always materialized the full output of a CTE query,treating WITH as an optimization fence (so that, for example, restrictionsfrom the outer query cannot be pushed into it). This is appropriate whenthe CTE query is INSERT/UPDATE/DELETE, or is recursive; but when the CTEquery is non-recursive and side-effect-free, there iss no hazard of changingthe query results by pushing restrictions down.Another argument for materialization is that it can avoid duplicatecomputation of an expensive WITH query --- but that only applies ifthe WITH query is called more than once in the outer query. Even thenit could still be a net loss, if each call has restrictions thatwould allow just a small part of the WITH query to be computed.Hence, let s change the behavior for WITH queries that are non-recursiveand side-effect-free. By default, we will inline them into the outerquery (removing the optimization fence) if they are called just once.If they are called more than once, we will keep the old behavior bydefault, but the user can override this and force inlining by specifyingNOT MATERIALIZED. Lastly, the user can force the old behavior byspecifying MATERIALIZED; this would mainly be useful when the query haddeliberately been employing WITH as an optimization fence to prevent apoor choice of plan.Andreas Karlsson, Andrew Gierth, David FetterDiscussion: https://postgr.es/m/87sh48ffhb.fsf@news-spur.riddles.org.uk
CREATE TABLE t (id int4, name text);INSERT INTO t(id,name) SELECT n, 'francs_' || nFROM generate_series(1,5000000) n;ALTER TABLE t ADD PRIMARY KEY (id);
WITH x AS (SELECT * FROM t)SELECT * FROM x where id=1;
postgres=# EXPLAIN ANALYZE WITH x AS (SELECT * FROM t)SELECT * FROM x where id=1;QUERY PLAN--------------------------------------------------------------------------CTE Scan on x (cost=81838.00..194338.00 rows=25000 width=36) (actual time=0.057..1557.140 rows=1 loops=1)Filter: (id = 1)Rows Removed by Filter: 4999999CTE x-> Seq Scan on t (cost=0.00..81838.00 rows=5000000 width=36) (actual time=0.050..525.329 rows=5000000 loops=1)Planning Time: 0.128 msExecution Time: 1591.979 ms(7 rows)Time: 1592.534 ms (00:01.593)
postgres=# EXPLAIN ANALYZE WITH x AS (SELECT * FROM t)SELECT * FROM x where id=1;QUERY PLAN--------------------------------------------------------------------------Index Scan using t_pkey on t (cost=0.43..8.45 rows=1 width=36) (actual time=0.021..0.022 rows=1 loops=1)Index Cond: (id = 1)Planning Time: 0.087 msExecution Time: 0.043 ms(4 rows)Time: 0.469 ms
postgres=# EXPLAIN ANALYZE WITH x AS MATERIALIZED (SELECT * FROM t)SELECT * FROM x where id=1;QUERY PLAN--------------------------------------------------------------------------CTE Scan on x (cost=81837.99..194337.97 rows=25000 width=36) (actual time=0.023..1607.012 rows=1 loops=1)Filter: (id = 1)Rows Removed by Filter: 4999999CTE x-> Seq Scan on t (cost=0.00..81837.99 rows=4999999 width=18) (actual time=0.015..556.583 rows=5000000 loops=1)Planning Time: 0.245 msExecution Time: 1640.071 ms(7 rows)Time: 1641.072 ms (00:01.641)
postgres=# EXPLAIN ANALYZE WITH x AS NOT MATERIALIZED (SELECT * FROM t)SELECT * FROM x where id=1;QUERY PLAN--------------------------------------------------------------------------Index Scan using t_pkey on t (cost=0.43..8.45 rows=1 width=18) (actual time=0.072..0.074 rows=1 loops=1)Index Cond: (id = 1)Planning Time: 0.134 msExecution Time: 0.099 ms(4 rows)Time: 0.801 ms
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69917105/viewspace-3168713/ ,如需转载,请注明出处,否则将追究法律责任。