Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1uvvcF-003kLM-Aw for pgsql-hackers@arkaria.postgresql.org; Tue, 09 Sep 2025 10:30:24 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1uvvcD-00BYSH-AX for pgsql-hackers@arkaria.postgresql.org; Tue, 09 Sep 2025 10:30:21 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1uvvcC-00BYS9-UT for pgsql-hackers@lists.postgresql.org; Tue, 09 Sep 2025 10:30:21 +0000 Received: from mail-yx1-xb12b.google.com ([2607:f8b0:4864:20::b12b]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1uvvc9-001VKl-1V for pgsql-hackers@lists.postgresql.org; Tue, 09 Sep 2025 10:30:20 +0000 Received: by mail-yx1-xb12b.google.com with SMTP id 956f58d0204a3-60f476e97f1so929067d50.2 for ; Tue, 09 Sep 2025 03:30:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1757413817; x=1758018617; darn=lists.postgresql.org; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=OyFraG1YGmqd5gMHk7rJ0hmiV4TfWYh6MZnKOaIS+e8=; b=X7cxutscaMjnVmKC/cOv/N3Udm0cEgS1ptgS//L5ilSstzFHXn1hdXR5OGyvaGM4w7 GlRXxRCpKVzatm8MeZRYGsl+FQF7ReQfTWk4Pq7w5JN/Qcb2/IWBTovDjG6Ieca9L/17 Te3I01w4ZGErBbDr3rAnw/OEDNFsmGAxV1R5oVFMfnmtk9XpbkJm2O1XAPB/ENnUcSeE yVLudk4oZM/PP0V4/k39VDkWsE1StBfnuCf3AsSLKyNawguaR+nbOQI2ool1Y2uXta5+ 3/kHUtECHYmest8WAC5hZMH/nPWiQKOFLnvsnVCcAdLf7VF/wbGdaOnZO8oFRFzuHO7D YcfA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1757413817; x=1758018617; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=OyFraG1YGmqd5gMHk7rJ0hmiV4TfWYh6MZnKOaIS+e8=; b=iCcHcFtBS0z6yWcCKLZ5AXom/fPe7sATY/0QBnWeJc7nAkNk1VpTf5gQwPikITNiY2 ML0ACqWBPQmXgtJkzBiqDAduJxbsaxVap5chT1QTgaQfjJ1LJL2ShWOkKAx3tFNbIq0e Wi80Yoi+24E3VuqhDXmph2VvpokYxXo9AmJYaegdxJCeVyieGJgLYZfj5MLe7aqichQP kEhxLRzTtK8hPgRXBmRuT49Zvw0WWE9ZLT7qKwfWH8TVXMn69sxNScnWAq1czsydHO0Z vnSeUJtKA/hiHVVnWUrSbqCLD5o4VGOUhsFXdEw+wMouQ9XF0lAEsf6tUr777ZL1ic2j oMPQ== X-Forwarded-Encrypted: i=1; AJvYcCXyCvev8/ykLZpP2f9+/b5VTMho1GAOYb34TMABvHJpLE1kX7FgC/sRcMu63zb+gSFo3kGfYtXpneQ2vqws@lists.postgresql.org X-Gm-Message-State: AOJu0YwSCJd+6h0exdsP7q1v/9HhVaNthpbiL2CUJ9O/8rOw2jE3rn39 oMiDD3Apluw6/61EZswnJX44vKp1G6CpyT2iwb7SfNMa+IIUN+RYIo8BS8WF6pvnVgLf+nIIqYS B9ubUiEHvd0oB6U0zjVSeVgTXrI4UC3Y= X-Gm-Gg: ASbGncsoQSdYuYQWzZrPDO6uAWy4x/CNkzaBJpKpayUi6PfmShlLz8rUlWNGI5jWusv m6ABSf6V0kujY6FjqWgBMsjVOcRwqGMyv+GG5raSN0Nbk1CcAg9w/PNmkU4VmNPX3FrcNhxqn15 /XhSdKcn+/uLWRkNMfm47RVJfKZIx0hy03Cv1wBOzveUqWSnkCoQdNVvdwdegD3ilv7S+L0rxwp LBU9pyTTQ== X-Google-Smtp-Source: AGHT+IFMDOu/dpnnceunXyJXn7z4pVzrwnkzdQ1NbfnkDAntQp4tDPtGFfP8eq4tQzPMpG0zVLsQ39+zIzp21NYOOUw= X-Received: by 2002:a05:690e:d55:b0:5fb:de81:ae9d with SMTP id 956f58d0204a3-6102277dff1mr9402447d50.10.1757413816714; Tue, 09 Sep 2025 03:30:16 -0700 (PDT) MIME-Version: 1.0 References: <87il22cj51.fsf@163.com> In-Reply-To: From: Richard Guo Date: Tue, 9 Sep 2025 19:30:04 +0900 X-Gm-Features: Ac12FXx1tf_2Aa9KyAW5I_ZMwqI7qTOPhnqTeagQK9bLfzh1WmtZnrkzdmpEIDo Message-ID: Subject: Re: Eager aggregation, take 3 To: Robert Haas Cc: Matheus Alcantara , Tom Lane , Tender Wang , Paul George , Andy Fan , PostgreSQL-development , pgsql-hackers@lists.postgresql.org Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Fri, Sep 5, 2025 at 11:37=E2=80=AFPM Robert Haas = wrote: > I spent a bit of time scrolling through this today. Here are a few > observations/review comments. Thanks for all the comments. > It looks as though this will create a bunch of RelOptInfo objects that > don't end up getting used for anything once the apply_at test in > generate_grouped_paths() fails. It seems to me that it would be better > to altogether avoid generating the RelOptInfo in that case. Hmm, that's not the case. make_grouped_join_rel() guarantees that for a given relation, if its grouped paths are not considered useful, and no grouped paths can be built by joining grouped input relations, then its grouped relation will not be created. IOW, we only create a grouped RelOptInfo if we've determined that we can generate useful grouped paths for it. In the case you mentioned, where the apply_at test in generate_grouped_paths() fails, it must mean that grouped paths can be built by joining its outer and inner relations. Also, note that calls to generate_grouped_paths() are always followed by calls to set_cheapest(). If we failed to generate any grouped paths for a grouped relation, the set_cheapest() call should already have reported an error. > I think it would be worth considering generating the partially grouped > relations in a second pass. Right now, as you progress from the bottom > of the join tree towards the top, you created grouped rels as you go. > But you could equally well finish planning everything up to the > scan/join target first and then go back and add grouped_rels to > relations where it seems worthwhile. Hmm, I don't think so. I think the presence of eager aggregation could change the best join order. For example, without eager aggregation, the optimizer might find that (A JOIN B) JOIN C the best join order. But with eager aggregation on B, the optimizer could prefer A JOIN (AGG(B) JOIN C). I'm not sure how we could find the best join order with eager aggregation applied without building the join tree from the bottom up. > I haven't done a detailed comparison of generate_grouped_paths() to > other parts of the code, but I have an uncomfortable feeling that it > might be rather similar to some existing code that probably already > exists in multiple, slightly-different versions. Is there any > refactoring we could do here? Yeah, we currently have several functions that do similar, but not exactly the same, things. Maybe some refactoring is possible -- maybe not -- I haven't looked into it closely yet. However, I'd prefer to address that in a separate patch if possible, since this issue also exists on master, and I want to avoid introducing such changes in this already large patch. > Do you need a test of this feature in combination with GEQO? You have > code for it but I don't immediately see a test. I didn't check > carefully, though. Good point. I do have manually tested GEQO by setting geqo_threshold to 2 and running the regression tests to check for any planning errors, crashes, or incorrect results. However, I'm not sure where test cases for GEQO should be added. I searched the regression tests and found only one explicit GEQO test, added back in 2009 (commit a43b190e3). It's not quite clear to me what the current policy is for adding GEQO test cases. Anyway, I will add some test cases in eager_aggregate.sql with geqo_threshold set to 2. > Overall I like the direction this is heading. I don't feel > well-qualified to evaluate whether all of the things that you're doing > are completely safe. The logic in is_var_in_aggref_only() and > is_var_needed_by_join() scares me a bit because I worry that the > checks are somehow non-exhaustive, but I don't know of a specific > hazard. That said, I think that modulo such issues, this has a good > chance of significantly improving performance for certain query > shapes. > > One thing to check might be whether you can construct any cases where > the strategy is applied too boldly. Given the safeguards you've put in > place that seems a little a little hard to construct. The most obvious > thing that occurs to me is an aggregate where combining is more > expensive than aggregating, so that the partial aggregation gives the > appearance of saving more work than it really does, but I can't > immediately think of a problem case. Another case could be where the > row counts are off, leading to us mistakenly believing that we're > going to reduce the number of rows that need to be processed when we > really don't. Of course, such a case would arguably be a fault of the > bad row-count estimate rather than this patch, but if the patch has > that problem frequently, it might need to be addressed. Still, I have > a feeling that the testing you've already been doing might have > surfaced such cases if they were common. Have you looked into how many > queries in the regression tests, or in TPC-H/DS, expend significant > planning effort on this strategy before discarding it? That might be a > good way to get a sense of whether the patch is too aggressive, not > aggressive enough, a mix of the two, or just right. I previously looked into the TPC-DS queries where eager aggregation was applied and didn't observe any regressions in planning time or execution time. I can run TPC-DS again to check the planning time for the remaining queries. - Richard