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.92) (envelope-from ) id 1jHBLD-0006Pd-5j for pgsql-hackers@arkaria.postgresql.org; Wed, 25 Mar 2020 19:05:27 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1jHBLB-0000CS-Vb for pgsql-hackers@arkaria.postgresql.org; Wed, 25 Mar 2020 19:05:25 +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 1jHBLB-0000CK-IZ for pgsql-hackers@lists.postgresql.org; Wed, 25 Mar 2020 19:05:25 +0000 Received: from mail-wr1-x441.google.com ([2a00:1450:4864:20::441]) by magus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1jHBL4-0005BJ-Rm for pgsql-hackers@postgresql.org; Wed, 25 Mar 2020 19:05:22 +0000 Received: by mail-wr1-x441.google.com with SMTP id p10so4637361wrt.6 for ; Wed, 25 Mar 2020 12:05:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=2ndquadrant-com.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to; bh=gQ5LgpckKt9n8UuFl3Q7X7T87tNzqn9uTVArF27oHKk=; b=hHjxEQj5eV+oMmMzAXfw7psgpeQqdzbq+3wbaYRs8APrdkF+5nep0M0O/9xQmxE8QZ DF2oiS8GQ2Vfb5RSox9w4Ud+1FJx9KLv817uWdhaW9/fuAG4RSngDUPxz47L5paohOmT tvyz+iSHcKgzZw+11ZE1BKfk1QmHQoBzh2lFBom5OKEz5+u5+GCwoMEz5Bhx2CkRRMkI 0p1G0jSbWV3x4+RHzxNxVMXQ/7M/ANdxKCwMgIev/cZPUGowh2dCrKBCmRAH2IBMVmfO hFHbXFcM4QCuqwZx/ecG7vhkx9FYiIi0TdWOmc0YwXXxGOTJg71FufnXpt8dyaX8f4r0 U3vQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to; bh=gQ5LgpckKt9n8UuFl3Q7X7T87tNzqn9uTVArF27oHKk=; b=X++uC7to160W61SwEqKrDUkbc5XYbmeY516nViAlJ4O2+SZcnjQkattlr8juvFthSD R0/rzE7RHLsJgLziCD+0r87x5nPntSnXYW7Rz1QyCs1TJG91GMETer/XnXFbKSa4LX55 gHOhgLJHUoH44PvIB0djfJqcmYBKygIuDuryQrIMXw/c3xgcB/BCEbR6JzV3dH0H3GL2 Sj7qg4r+ARFKoM0c82YY7cJPTHwqj+Zsh/Y5oDJsO5MPbBL/3sln6Z8YarKW0jQCkVjJ iE12MuoubhTkEKlzNrvgr/fOupq0YBYW9GLdKcuGPJLbW2brNNyXXyfss5Ob6wn46Wth 3vDA== X-Gm-Message-State: ANhLgQ10yvzHV6oy4s+9jiihRkF9T7F+GhkzR5YBGfAoUT5ez57U+pGI XC0daTmCTI46HOz/Vlbii/yF3w== X-Google-Smtp-Source: ADFU+vsFPF6KXjkPLlUxxPNcQh5jv4StWwMNpO1qidcJnAmXcq6y+096UQyDWvYLYgd8x5RIoUxZQw== X-Received: by 2002:adf:f646:: with SMTP id x6mr5009222wrp.19.1585163117685; Wed, 25 Mar 2020 12:05:17 -0700 (PDT) Received: from localhost (ip-86-49-253-141.net.upcbroadband.cz. [86.49.253.141]) by smtp.gmail.com with ESMTPSA id f1sm26809940wrv.37.2020.03.25.12.05.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 25 Mar 2020 12:05:15 -0700 (PDT) Date: Wed, 25 Mar 2020 20:05:13 +0100 From: Tomas Vondra To: Etsuro Fujita Cc: Ashutosh Bapat , Mark Dilger , amul sul , Robert Haas , Thomas Munro , Amit Langote , Rajkumar Raghuwanshi , Etsuro Fujita , Dmitry Dolgov <9erthalion6@gmail.com>, Antonin Houska , PostgreSQL-development , Ashutosh Bapat Subject: Re: [HACKERS] advanced partition matching algorithm for partition-wise join Message-ID: <20200325190513.rmxr7swainc64io5@development> References: <4F6838E1-0FE8-4B92-B126-809866A064DE@enterprisedb.com> <768B0ED5-F2AA-4CB8-8DA3-41E2148CF42A@enterprisedb.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Disposition: inline In-Reply-To: List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk Hi, I've started reviewing the patch a couple days ago. I haven't done any extensive testing, but I do have a bunch of initial comments that I can share now. 1) I wonder if this needs to update src/backend/optimizer/README, which does have a section about partitionwise joins. It seems formulated in a way that that probably covers even this more advanced algorithm, but maybe it should mention handling of default partitions etc.? There certainly needs to be some description of the algorithm somewhere, either in a README or before a suitable function. It doesn't have to be particularly detailed, a rough outline of the matching would be enough, so that readers don't have to rebuild the knowledge from pieces scattered around various comments. 2) Do we need another GUC enabling this more complex algorithm? In PG11 the partitionwise join is disabled by default, on the grounds that it's expensive and not worth it by default. How much more expensive is this? Maybe it makes sense to allow enabling only the "simple" approach? 3) This comment in try_partitionwise_join is now incorrect, because the condition may be true even for partitioned tables with (nparts == 0). /* Nothing to do, if the join relation is not partitioned. */ if (joinrel->part_scheme == NULL || joinrel->nparts == 0) return; Moreover, the condition used to be if (!IS_PARTITIONED_REL(joinrel)) return; which is way more readable. I think it's net negative to replace these "nice" macros with clear meaning with complex conditions. If needed, we can invent new macros. There are many other places where the patch replaces macros with less readable conditions. 4) I'm a bit puzzled how we could get here with non-partitioned rels? /* * We can not perform partitionwise join if either of the joining relations * is not partitioned. */ if (!IS_PARTITIONED_REL(rel1) || !IS_PARTITIONED_REL(rel2)) return; 5) I find the "merged" flag in RelOptInfo rather unclear, because it does not clearly indicate what was merged. Maybe something like partbounds_merged would be better? 6) The try_partitionwise_join function is getting a bit too long and harder to understand. The whole block in if (joinrel->nparts == -1) { ... } seems rather well isolated, so I propose to move it to a separate function responsible only for the merging. We can simply call it on the joinrel, and make it return right away if (joinrel->nparts == -1). 7) I'd suggest not to reference exact functions in comments unless abolutely necessary, because it's harder to maintain and it does not really explain purpose of the struct/code. E.g. consider this: /* Per-partitioned-relation data for merge_list_bounds()/merge_range_bounds() */ typedef struct PartitionMap { ... } Why does it matter where is the struct used? That's pretty trivial to find using 'git grep' or something. Instead the comment should explain the purpose of the struct. regards -- Tomas Vondra http://www.2ndQuadrant.com PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services