Is it possible to have two copies of a table clustered in different arrangements seamlessly?

To have the data held in two different physical sequences one must store the data twice. This can be achieved by defining a second, covering index. A covering index contains all of the columns required by a query. This way the optimiser has no need to refer to the base table to read further values and is unlikely to revert to a base table scan for the query plan. The optimiser performs an index-only scan. As the choice of index is made by the optimiser and not be the programmer no application code need be altered to take advantage during reads. No further objects are required to maintain consistency during writes.

The columns used in the WHERE clause will be the leading columns of the index. The sequence of the other columns is unimportant. As and when PostgreSQL supports the INCLUDE syntax this index can be changed to use it.

The downsides include a) extra disk to store this data b) additional latency during writes to maintain the index c) more system maintenance required for reorgs and such, and d) as queries change the covering index(es) have to change to match e) correspondingly larger and longer backups and restores.


You can create a materialized view on your table:

CREATE MATERIALIZED VIEW thecopy AS SELECT * FROM mytable;

Then add a unique index that matches your PK on mytable (you cannot add a 'real' PK there as it is not a 'real' table):

CREATE UNIQUE INDEX ON thecopy (node_id, pricedate, hour);

So your copy is there. If you want to cluster it, you need an index for it:

CREATE INDEX ON thecopy (pricedate);
CLUSTER thecopy USING thecopy_pricedate_idx;
-- You can also do 
-- ALTER MATERIALIZED VIEW thecopy CLUSTER ON thecopy_pricedate_idx;
-- https://www.postgresql.org/docs/current/static/sql-altermaterializedview.html

Then whenever you need it (basically after the daily data load finishes), do a

REFRESH MATERIALIZED VIEW [CONCURRENTLY] thecopy;

And then change the second type of queries to go to the MV instead of the table.