5 ms·
This is incorrect. If you use a CTE more than once in a query, Postgres will materialize that data into a temp table that has no indexes. If that CTE gets joine
by srcreigh 4y ago
This is incorrect. If you use a CTE more than once in a query, Postgres will materialize that data into a temp table that has no indexes. If that CTE gets joined a lot, it will incur many O(N) searched through unindexed data.
I've seen cases where a few GBs of product data gets pulled into a CTE this way. Queries take 10s to complete from processing GBs of unindexed data
- deleted 4y ago[deleted]
- btown 4y agoIs there a way to force the temp table to have indices within the CTE definition?
- srcreigh 4y agoNo, but this would make an incredible Postgres extension. (I’d also love one that lets Postgres use a covering index for primary storage. This can reduce data size and load less data off disk due to locality. MySQL has this by default and SQLite has it via WITHOUT ROWID tables.)
- Zanfa 4y agoWow, this is amazing. Just the other day I was staring at a query with multiple CTEs that took 20+ seconds to run. Ended up adding an additional WHERE clause on an indexed column to the slowest CTE, which took the execution time down to 100s of ms. Just tried the original query, but with explicitly not materialized CTEs and the runtime was basically as fast as the manually pre-filtered solution.
- srcreigh 4y agoNot materializing lets Postgres push extra where clauses and join conditions into the CTE so this makes sense! Now you know why I spam all the “CTEs are amazing” threads about materialization (there have been 5 or so in the last few months)