I have a large table in PostgreSQL 9.2, which I divided as described in the manual . Almost! My real partition key is not in the partitioned table itself, but in the joined table like this (simplified):
-- millions to tens of millions of rows CREATE TABLE data ( slice_id integer NOT NULL, point_id integer NOT NULL, -- ... data columns ..., CONSTRAINT pk_data PRIMARY KEY (slice_id, point_id), CONSTRAINT fk_data_slice FOREIGN KEY (slice_id) REFERENCES slice (id) CONSTRAINT fk_data_point FOREIGN KEY (point_id) REFERENCES point (id) ) -- hundreds to thousands of rows CREATE TABLE slice ( id serial NOT NULL, partition_date timestamp without time zone NOT NULL, other_date timestamp without time zone NOT NULL, int_key integer NOT NULL CONSTRAINT pk_slice PRIMARY KEY (id) ) -- about 40,000 rows CREATE TABLE point ( -- ... similar to "slice" ... )
The partition table ( data ) contains rows for each combination of point and slice , each of which has a composite key. I want to split it only into one of the key columns, partition_date , which is part of slice . Of course, the limitations of checking for my child tables cannot include this directly, so instead I include a range of all the slice.id values โโcorresponding to this partition_date , for example:
ALTER TABLE data_part_123 ADD CONSTRAINT ck_data_part_123 CHECK (slice_id >= 1234 AND slice_id <= 1278);
All this works great for inserting data. However, queries do not use the specified CHECK constraint. For instance.
SELECT * FROM data d JOIN slice s ON d.slice_id = s.id WHERE s.partition_date = '2013-07-23'
I see in the query plan that this still scans all child tables. I tried to rewrite the query in several ways, including CTE and subselect, but that did not help.
Is there a way to get the scheduler to "understand" my partitioning scheme? I really don't want to duplicate the partition key millions of times in the data table.
The request scheme is as follows:
Aggregate (cost=539243.88..539243.89 rows=1 width=0) -> Hash Join (cost=8.88..510714.02 rows=11411945 width=0) Hash Cond: (d.slice_id = s.id) -> Append (cost=0.00..322667.41 rows=19711542 width=4) -> Seq Scan on data d (cost=0.00..0.00 rows=1 width=4) -> Seq Scan on data_part_123 d (cost=0.00..135860.10 rows=8299610 width=4) -> Seq Scan on data_part_456 d (cost=0.00..186807.31 rows=11411931 width=4) -> Hash (cost=7.09..7.09 rows=143 width=4) -> Seq Scan on slice s (cost=0.00..7.09 rows=143 width=4) Filter: (partition_date = '2013-07-23 00:00:00'::timestamp without time zone)