How do I move PostgreSQL temp_files to a different tablespace/disk for CURSORs

All we need is an easy explanation of the problem, so here it is.

While working on performance improvements on our PostgreSQL database (Ubuntu Focal, PostgreSQL 13.3), I created a "temporary" tablespace on a fast local NVME drive. This works well and both temporary tables and temp_files created by large queries end up there, taking a lot of load off the main data drive.

However, we use server side CURSORS a lot, and it appears that temp_files created by those always end up on the main data volume, causing a lot more I/O than we really want there.

2022-03-13 00:59:51.692 UTC 1350170 [email protected] LOG: temporary file: path "base/pgsql_tmp/pgsql_tmp1350170.54", size 564228392

2022-03-13 00:59:51.692 UTC 1350170 [email protected] STATEMENT: FETCH FORWARD 5569 FROM "xx"

I’ve done about as much work_mem tuning as I can, but many of our queries are large (temp_files are often over 1GB). Our biggest bottleneck is I/O on the data drive. So, if I can get those temp_files onto the separate local NVME drive instead, that’d do wonders.

I’ve seen a few places suggest replacing the pgsql_tmp dir from ~/main/base/pgsql_tmp with a symlink to the other drive, but also warnings that that isn’t necessarily safe.

Is this a safe way to do this, or is there another, better way? Is there some way to tell PostgreSQL to put temp_files generated by CURSORS onto the temporary drive?


How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

If these cursors are declared WITH HOLD, then I think you are running into this bit from src/backend/storage/file/fd.c:

 * BUT: if the temp file is slated to outlive the current transaction,
 * force it into the database's default tablespace, so that it will not
 * pose a threat to possible tablespace drop attempts.
if (numTempTableSpaces > 0 && !interXact)

Perhaps this should be documented in user-space, not just the source-code comments.

I don’t see that there is anything you can do about it, other than remove the !interXact test and compile your own binaries.

I might find symlinking ~/main/base/pgsql_tmp to be preferable to that. Did the people warning against it say why?

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from or, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply