Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1hDlOn-0004hU-7l for pgsql-hackers@arkaria.postgresql.org; Tue, 09 Apr 2019 07:42:29 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1hDlOk-00084T-V2 for pgsql-hackers@arkaria.postgresql.org; Tue, 09 Apr 2019 07:42:26 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1hDlOk-00084J-MD for pgsql-hackers@lists.postgresql.org; Tue, 09 Apr 2019 07:42:26 +0000 Received: from tama50.ecl.ntt.co.jp ([129.60.39.147]) by magus.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1hDlOd-0000mX-9Q for pgsql-hackers@lists.postgresql.org; Tue, 09 Apr 2019 07:42:26 +0000 Received: from vc2.ecl.ntt.co.jp (vc2.ecl.ntt.co.jp [129.60.86.154]) by tama50.ecl.ntt.co.jp (8.13.8/8.13.8) with ESMTP id x397g8To014783; Tue, 9 Apr 2019 16:42:08 +0900 Received: from vc2.ecl.ntt.co.jp (localhost [127.0.0.1]) by vc2.ecl.ntt.co.jp (Postfix) with ESMTP id BF0E16398FF; Tue, 9 Apr 2019 16:42:08 +0900 (JST) Received: from jcms-pop11.ecl.ntt.co.jp (jcms-pop11.ecl.ntt.co.jp [129.60.87.132]) by vc2.ecl.ntt.co.jp (Postfix) with ESMTP id 7EB426398F7; Tue, 9 Apr 2019 16:42:08 +0900 (JST) Received: from hosoyahp (unknown [129.60.241.74]) by jcms-pop11.ecl.ntt.co.jp (Postfix) with ESMTPSA id 60D3070C09AC; Tue, 9 Apr 2019 16:42:08 +0900 (JST) From: "Yuzuko Hosoya" References: <9dc22159-4869-dd2b-feb5-c39af3c01a7e@lab.ntt.co.jp> <00c101d4ede0$babd4390$3037cab0$@lab.ntt.co.jp> <20190409.102848.252476604.horiguchi.kyotaro@lab.ntt.co.jp> <20190409.103317.20446083.horiguchi.kyotaro@lab.ntt.co.jp> In-Reply-To: <20190409.103317.20446083.horiguchi.kyotaro@lab.ntt.co.jp> Subject: RE: Problem with default partition pruning Date: Tue, 9 Apr 2019 16:41:47 +0900 Message-ID: <00cf01d4eea7$afa43370$0eec9a50$@lab.ntt.co.jp> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_NextPart_000_00D0_01D4EEF3.1F8C2990" X-Mailer: Microsoft Outlook 15.0 Content-language: ja Thread-index: AQF9mTaRY9vJgw/ba5uOY8SApfldLQGdaKIsAX6Rm2kCQJtMQaa3LdZw X-CC-Mail-RelayStamp: 1 To: "'Kyotaro HORIGUCHI'" Cc: , , , X-TM-AS-MML: disable List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk This is a multipart message in MIME format. ------=_NextPart_000_00D0_01D4EEF3.1F8C2990 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Horiguchi-san, Thanks for your comments. > -----Original Message----- > From: Kyotaro HORIGUCHI [mailto:horiguchi.kyotaro@lab.ntt.co.jp] > Sent: Tuesday, April 09, 2019 10:33 AM > To: hosoya.yuzuko@lab.ntt.co.jp > Cc: Langote_Amit_f8@lab.ntt.co.jp; thibaut.madelaine@dalibo.com; imai.yoshikazu@jp.fujitsu.com; > pgsql-hackers@lists.postgresql.org > Subject: Re: Problem with default partition pruning > > Sigh.. > > At Tue, 09 Apr 2019 10:28:48 +0900 (Tokyo Standard Time), Kyotaro HORIGUCHI > wrote in > <20190409.102848.252476604.horiguchi.kyotaro@lab.ntt.co.jp> > > As the second thought. Partition constraint is not constraint > > expression so that's fair to apply partqual ignoring > > constraint_exclusion. The variable is set false to skip useless > > expression evaluation on all partitions, but partqual should be > > evaluated just once. Sorry for my confusion. > > > > So still it is wrong that the new code is added in > > gen_partprune_steps_internal. > > So still it is wrong that the new code is added at the beginning of the loop on clauses in > gen_partprune_steps_internal. > > > If partqual results true and the clause > > is long, the partqual is evaluated uselessly at every recursion. > > > > Maybe we should do that when we find that the current clause doesn't > > match part attributes. Specifically just after the for loop "for (i = > > 0 ; i < part_scheme->partnattrs; i++)". > I think we should check whether WHERE clause contradicts partition constraint even when the clause matches part attributes. So I moved "if (partqual)" block to the beginning of the loop you mentioned. I'm attaching the latest version. Could you please check it again? Best regards, Yuzuko Hosoya ------=_NextPart_000_00D0_01D4EEF3.1F8C2990 Content-Type: application/octet-stream; name="v4_ignore_contradictory_where_clauses_at_partprune_step.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="v4_ignore_contradictory_where_clauses_at_partprune_step.patch" diff --git a/src/backend/partitioning/partprune.c = b/src/backend/partitioning/partprune.c=0A= index 5cd740a..11e3e7a 100644=0A= --- a/src/backend/partitioning/partprune.c=0A= +++ b/src/backend/partitioning/partprune.c=0A= @@ -850,32 +850,13 @@ = gen_partprune_steps_internal(GeneratePruningStepsContext *context,=0A= * an arg. To indicate that to the pruning code, we=0A= * must construct a dummy PartitionPruneStepCombine=0A= * whose source_stepids is set to an empty List.=0A= - * However, if we can prove using constraint exclusion=0A= - * that the clause refutes the table's partition=0A= - * constraint (if it's sub-partitioned), we need not=0A= - * bother with that. That is, we effectively ignore=0A= - * this OR arm.=0A= */=0A= - List *partconstr =3D rel->partition_qual;=0A= PartitionPruneStep *orstep;=0A= =0A= /* Just ignore this argument. */=0A= if (arg_contradictory)=0A= continue;=0A= =0A= - if (partconstr)=0A= - {=0A= - partconstr =3D (List *)=0A= - expression_planner((Expr *) partconstr);=0A= - if (rel->relid !=3D 1)=0A= - ChangeVarNodes((Node *) partconstr, 1,=0A= - rel->relid, 0);=0A= - if (predicate_refuted_by(partconstr,=0A= - list_make1(arg),=0A= - false))=0A= - continue;=0A= - }=0A= -=0A= orstep =3D gen_prune_step_combine(context, NIL,=0A= PARTPRUNE_COMBINE_UNION);=0A= arg_stepids =3D lappend_int(arg_stepids, orstep->step_id);=0A= @@ -951,6 +932,30 @@ = gen_partprune_steps_internal(GeneratePruningStepsContext *context,=0A= bool clause_is_not_null =3D false;=0A= PartClauseInfo *pc =3D NULL;=0A= List *clause_steps =3D NIL;=0A= + List *partconstr =3D rel->partition_qual;=0A= +=0A= + /*=0A= + * If this clause can be proved false for this partition,=0A= + * given its partition constraint, we can ignore it,=0A= + * that is not try to pass it to the pruning code.=0A= + * We should do that especially to avoid pruning code=0A= + * wrongly failing to prune the default partition.=0A= + */=0A= + if (partconstr)=0A= + {=0A= + partconstr =3D (List *)=0A= + expression_planner((Expr *) partconstr);=0A= + if (rel->relid !=3D 1)=0A= + ChangeVarNodes((Node *) partconstr, 1,=0A= + rel->relid, 0);=0A= + if (predicate_refuted_by(partconstr,=0A= + list_make1(clause),=0A= + false))=0A= + {=0A= + *contradictory =3D true;=0A= + return NIL;=0A= + }=0A= + }=0A= =0A= switch (match_clause_to_partition_key(rel, context,=0A= clause, partkey, i,=0A= diff --git a/src/test/regress/expected/partition_prune.out = b/src/test/regress/expected/partition_prune.out=0A= index b46951c..716155d 100644=0A= --- a/src/test/regress/expected/partition_prune.out=0A= +++ b/src/test/regress/expected/partition_prune.out=0A= @@ -592,6 +592,24 @@ explain (costs off) select * from rlp where a < 1 = or (a > 20 and a < 25);=0A= Filter: ((a < 1) OR ((a > 20) AND (a < 25)))=0A= (5 rows)=0A= =0A= +-- where clause contradicts sub-partition's constraint =0A= +explain (costs off) select * from rlp where a =3D 20 or a =3D 40;=0A= + QUERY PLAN =0A= +----------------------------------------=0A= + Append=0A= + -> Seq Scan on rlp4_1=0A= + Filter: ((a =3D 20) OR (a =3D 40))=0A= + -> Seq Scan on rlp5_default=0A= + Filter: ((a =3D 20) OR (a =3D 40))=0A= +(5 rows)=0A= +=0A= +explain (costs off) select * from rlp3 where a =3D 20; /* empty */=0A= + QUERY PLAN =0A= +--------------------------=0A= + Result=0A= + One-Time Filter: false=0A= +(2 rows)=0A= +=0A= -- redundant clauses are eliminated=0A= explain (costs off) select * from rlp where a > 1 and a =3D 10; /* only = default */=0A= QUERY PLAN =0A= diff --git a/src/test/regress/sql/partition_prune.sql = b/src/test/regress/sql/partition_prune.sql=0A= index abc6d9e..a5e8109 100644=0A= --- a/src/test/regress/sql/partition_prune.sql=0A= +++ b/src/test/regress/sql/partition_prune.sql=0A= @@ -85,6 +85,10 @@ explain (costs off) select * from rlp where a =3D 29;=0A= explain (costs off) select * from rlp where a >=3D 29;=0A= explain (costs off) select * from rlp where a < 1 or (a > 20 and a < = 25);=0A= =0A= +-- where clause contradicts sub-partition's constraint=0A= +explain (costs off) select * from rlp where a =3D 20 or a =3D 40;=0A= +explain (costs off) select * from rlp3 where a =3D 20; /* empty */=0A= +=0A= -- redundant clauses are eliminated=0A= explain (costs off) select * from rlp where a > 1 and a =3D 10; /* only = default */=0A= explain (costs off) select * from rlp where a > 1 and a >=3D15; /* rlp3 = onwards, including default */=0A= ------=_NextPart_000_00D0_01D4EEF3.1F8C2990--