When I excluded the non indexed search criteria the query on aggregate used the indexes on each partition, without specifying the constraint exclusion criteria. When I added the constraint exclusion criteria to the non indexed criteria, it still used seq scans.
I ended up getting an acceptable plan by using a subquery on the indexed partition and using those results to scan for the unindexed value. On Wed, Sep 21, 2016 at 12:37 PM, Mike Broers <mbro...@gmail.com> wrote: > Thanks for your response - Is 'selectively choosing what partition' > different than utilizing each partitions index when scanning each > partition? To clarify, I expect to find results in each partition, but to > have postgres use each partitions index instead of full table scans. It > seems redundant to add a where clauses to match each exclusion criteria but > i will try that and report back - thank you for the suggestion. > > On Wed, Sep 21, 2016 at 12:15 PM, Ganesh Kannan <ganesh.kannan@ > weatheranalytics.com> wrote: > >> Postgres does not have capability to selectively choose child tables >> unless the query's "WHERE" clause is simple, and it matches (exactly) the >> CHECK constraint definition. I have resolved similar issue by explicitly >> adding check constraint expression in every SQL against the master table. >> This is also determined by the constraint_exclusion setting value. Check >> the manual (9.5): https://www.postgresql.org/docs/current/static/ddl-pa >> rtitioning.html. >> >> >> I would try tweaking WHERE clause to match Check constraint definition. >> Global partitioning index (like in Oracle) would help, but its just my wish. >> >> >> >> Regards, >> Ganesh Kannan >> >> >> >> ------------------------------ >> *From:* pgsql-performance-ow...@postgresql.org < >> pgsql-performance-ow...@postgresql.org> on behalf of Mike Broers < >> mbro...@gmail.com> >> *Sent:* Wednesday, September 21, 2016 12:53 PM >> *To:* pgsql-performance@postgresql.org >> *Subject:* [PERFORM] query against single partition uses index, against >> master table does seq scan >> >> Hello, I am curious about the performance of queries against a master >> table that seem to do seq scans on each child table. When the same query >> is issued at a partition directly it uses the partition index and is very >> fast. >> >> The partition constraint is in the query criteria. We have non >> overlapping check constraints and constraint exclusion is set to partition. >> >> Here is the master table >> Column Type >> Modifiers >> aggregate_id bigint not null default >> nextval('seq_aggregate'::regclass) >> landing_id integer not null >> client_program_id integer >> sequence_number bigint >> start_datetime timestamp without time zone not null >> end_datetime timestamp without time zone not null >> body jsonb not null >> client_parsing_status_code character(1) >> validation_status_code character(1) >> client_parsing_datetime timestamp without time zone >> validation_datetime timestamp without time zone >> latest_flag_datetime timestamp without time zone >> latest_flag boolean not null >> Indexes: >> "pk_aggregate" PRIMARY KEY, btree (aggregate_id) >> "ix_aggregate_landing_id_aggregate_id_parsing_status" btree >> (landing_id, aggregate_id, client_parsing_status_code) >> "ix_aggregate_landing_id_start_datetime" btree (landing_id, >> start_datetime) >> "ix_aggregate_latest_flag" btree (latest_flag_datetime) WHERE >> latest_flag = false >> "ix_aggregate_validation_status_code" btree (validation_datetime) >> WHERE validation_status_code = 'P'::bpchar AND latest_flag = true >> Check constraints: >> "ck_aggregate_client_parsing_status_code" CHECK >> (client_parsing_status_code IS NULL OR (client_parsing_status_code = ANY >> (ARRAY['P'::bpchar, 'F'::bpchar, 'I'::bpchar]))) >> "ck_aggregate_validation_status_code" CHECK (validation_status_code >> IS NULL OR (validation_status_code = ANY (ARRAY['P'::bpchar, 'F'::bpchar, >> 'I'::bpchar]))) >> Foreign-key constraints: >> "fk_aggregate_client_program" FOREIGN KEY (client_program_id) >> REFERENCES client_program(client_program_id) >> "fk_aggregate_landing" FOREIGN KEY (landing_id) REFERENCES >> landing(landing_id) >> Number of child tables: 17 (Use \d+ to list them.) >> >> and here is a child table showing a check constraint >> Table "stage.aggregate__00007223" >> Column Type >> Modifiers >> ────────────────────────── ─────────────────────────── >> aggregate_id bigint not null default >> nextval('seq_aggregate'::regclass) >> landing_id integer not null >> client_program_id integer >> sequence_number bigint >> start_datetime timestamp without time zone not null >> end_datetime timestamp without time zone not null >> body jsonb not null >> client_parsing_status_code character(1) >> validation_status_code character(1) >> client_parsing_datetime timestamp without time zone >> validation_datetime timestamp without time zone >> latest_flag_datetime timestamp without time zone >> latest_flag boolean not null >> Indexes: >> "pk_aggregate__00007223" PRIMARY KEY, btree (aggregate_id), >> tablespace "archive" >> "ix_aggregate__00007223_landing_id_aggregate_id_parsing_status" >> btree (landing_id, aggregate_id, client_parsing_status_code), tablespace >> "archive" >> "ix_aggregate__00007223_landing_id_start_datetime" btree >> (landing_id, start_datetime), tablespace "archive" >> "ix_aggregate__00007223_latest_flag" btree (latest_flag_datetime) >> WHERE latest_flag = false, tablespace "archive" >> "ix_aggregate__00007223_validation_status_code" btree >> (validation_datetime) WHERE validation_status_code = 'P'::bpchar AND >> latest_flag = true, tablespace "archive" >> Check constraints: >> "ck_aggregate__00007223_landing_id" CHECK (landing_id >= 7223 AND >> landing_id < 9503) >> "ck_aggregate_client_parsing_status_code" CHECK >> (client_parsing_status_code IS NULL OR (client_parsing_status_code = ANY >> (ARRAY['P'::bpchar, 'F'::bpchar, 'I'::bpchar]))) >> "ck_aggregate_validation_status_code" CHECK (validation_status_code >> IS NULL OR (validation_status_code = ANY (ARRAY['P'::bpchar, 'F'::bpchar, >> 'I'::bpchar]))) >> Inherits: aggregate >> Tablespace: "archive" >> >> Here is an example of the query explain plan against the master table: >> >> select landing_id from landing L >> where exists >> ( >> select landing_id >> from stage.aggregate A >> WHERE (A.body#>>'{Cost}')::BIGINT >= 1000000000 >> and L.landing_id = A.Landing_id >> ) >> and L.source_id = 36 >> >> >> Hash Join (cost=59793745.91..59793775.14 rows=28 width=4) >> Hash Cond: (a.landing_id = l.landing_id) >> -> HashAggregate (cost=59792700.41..59792721.46 rows=2105 width=4) >> Group Key: a.landing_id >> -> Append (cost=0.00..59481729.32 rows=124388438 width=4) >> -> Seq Scan on aggregate a (cost=0.00..0.00 rows=1 >> width=4) >> Filter: (((body #>> '{Cost}'::text[]))::bigint >= >> 1000000000) >> -> Seq Scan on aggregate__00000000 a_1 >> (cost=0.00..1430331.50 rows=2105558 width=4) >> Filter: (((body #>> '{Cost}'::text[]))::bigint >= >> 1000000000) >> -> Seq Scan on aggregate__00000470 a_2 >> (cost=0.00..74082.10 rows=247002 width=4) >> Filter: (((body #>> '{Cost}'::text[]))::bigint >= >> 1000000000) >> -> Seq Scan on aggregate__00001435 a_3 >> (cost=0.00..8174909.44 rows=17610357 width=4) >> Filter: (((body #>> '{Cost}'::text[]))::bigint >= >> 1000000000) >> -> Seq Scan on aggregate__00001685 a_4 >> (cost=0.00..11011311.44 rows=23516624 width=4) >> Filter: (((body #>> '{Cost}'::text[]))::bigint >= >> 1000000000) >> -> Seq Scan on aggregate__00003836 a_5 >> (cost=0.00..5833050.44 rows=13102557 width=4) >> Filter: (((body #>> '{Cost}'::text[]))::bigint >= >> 1000000000) >> -> Seq Scan on aggregate__00005638 a_6 >> (cost=0.00..5950768.16 rows=12342003 width=4) >> Filter: (((body #>> '{Cost}'::text[]))::bigint >= >> 1000000000) >> -> Seq Scan on aggregate__00007223 a_7 >> (cost=0.00..6561806.24 rows=13203237 width=4) >> Filter: (((body #>> '{Cost}'::text[]))::bigint >= >> 1000000000) >> -> Seq Scan on aggregate__00009503 a_8 >> (cost=0.00..5420961.64 rows=10931794 width=4) >> Filter: (((body #>> '{Cost}'::text[]))::bigint >= >> 1000000000) >> -> Seq Scan on aggregate__00011162 a_9 >> (cost=0.00..4262902.64 rows=8560011 width=4) >> Filter: (((body #>> '{Cost}'::text[]))::bigint >= >> 1000000000) >> -> Seq Scan on aggregate__00012707 a_10 >> (cost=0.00..4216271.28 rows=9077921 width=4) >> Filter: (((body #>> '{Cost}'::text[]))::bigint >= >> 1000000000) >> -> Seq Scan on aggregate__00014695 a_11 >> (cost=0.00..3441205.72 rows=7674495 width=4) >> Filter: (((body #>> '{Cost}'::text[]))::bigint >= >> 1000000000) >> -> Seq Scan on aggregate__00016457 a_12 >> (cost=0.00..688010.74 rows=1509212 width=4) >> Filter: (((body #>> '{Cost}'::text[]))::bigint >= >> 1000000000) >> -> Seq Scan on aggregate__00016805 a_13 >> (cost=0.00..145219.14 rows=311402 width=4) >> Filter: (((body #>> '{Cost}'::text[]))::bigint >= >> 1000000000) >> -> Seq Scan on aggregate__00016871 a_14 (cost=0.00..21.40 >> rows=190 width=4) >> Filter: (((body #>> '{Cost}'::text[]))::bigint >= >> 1000000000) >> -> Seq Scan on aggregate__00016874 a_15 >> (cost=0.00..478011.62 rows=1031110 width=4) >> Filter: (((body #>> '{Cost}'::text[]))::bigint >= >> 1000000000) >> -> Seq Scan on aggregate__00017048 a_16 (cost=0.00..21.40 >> rows=190 width=4) >> Filter: (((body #>> '{Cost}'::text[]))::bigint >= >> 1000000000) >> -> Seq Scan on aggregate__00017049 a_17 >> (cost=0.00..1792844.42 rows=3164774 width=4) >> Filter: (((body #>> '{Cost}'::text[]))::bigint >= >> 1000000000) >> -> Hash (cost=1042.69..1042.69 rows=225 width=4) >> -> Seq Scan on landing l (cost=0.00..1042.69 rows=225 width=4) >> Filter: (source_id = 36) >> >> And here is an example of the query using the index when ran against a >> partition directly >> >> select landing_id from landing L >> where exists >> ( >> select landing_id >> from stage.aggregate__00007223 A >> WHERE (A.body#>>'{Cost}')::BIGINT >= 1000000000 >> and L.landing_id = A.Landing_id >> ) >> and L.source_id = 36 >> >> Nested Loop Semi Join (cost=0.56..3454.75 rows=5 width=4) >> -> Seq Scan on landing l (cost=0.00..1042.69 rows=225 width=4) >> Filter: (source_id = 36) >> -> Index Scan using ix_aggregate__00007223_landing_id_start_datetime >> on aggregate__00007223 a (cost=0.56..359345.74 rows=36173 width=4) >> Index Cond: (landing_id = l.landing_id) >> Filter: (((body #>> '{Cost}'::text[]))::bigint >= 1000000000) >> >> >> The parent table never had rows, and pg_class had relpages=0. I saw a >> suggestion in a different thread about updating this value to greater than >> 0 so I tried that but didnt get a different plan. We have >> autovacuum/analyze enabled and also run nightly vacuum/analyze on the >> database to keep stats up to date. >> >> I'm new to troubleshooting partition query performance and not sure what >> I am missing here. Any advice is appreciated. >> > >