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.96) (envelope-from ) id 1vL6Uw-004AWi-0N for pgsql-hackers@arkaria.postgresql.org; Mon, 17 Nov 2025 21:10:54 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vL6Tu-0024Vr-0O for pgsql-hackers@arkaria.postgresql.org; Mon, 17 Nov 2025 21:09:50 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vL6Tt-0024Vj-26 for pgsql-hackers@lists.postgresql.org; Mon, 17 Nov 2025 21:09:50 +0000 Received: from mail-ua1-x92a.google.com ([2607:f8b0:4864:20::92a]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1vL6Tq-0003Iz-2x for pgsql-hackers@postgresql.org; Mon, 17 Nov 2025 21:09:49 +0000 Received: by mail-ua1-x92a.google.com with SMTP id a1e0cc1a2514c-9372310418bso1330056241.3 for ; Mon, 17 Nov 2025 13:09:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1763413786; x=1764018586; darn=postgresql.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=X5YC9CjG2cnLhN4+Emrv86sQuYMgj2JFxcP4g4fQZXE=; b=lQd3n9m5QTYG81veHo2FqiZRRTsydikjn6SKI24YgLUp55SSiVMJmN9tRQXGrerncX 1ATYkQFpIRY0gebOwLEVm29nc1HPNovcNDiOBV6tTe/vSa9P0ZcHBwH6CVdXhFcsUFir HugHuOAsEt0BaYBROSCeFjpCLEm9GsXnIWvLzCLbEQvrls6jal+xaJCQq/F4vrQSETnm FmCF6N3Z6/F6OIvFUl816NQrl5m3vwWkt7wp6GKPObtz19a/WhElClggB3EGvhmuB5PH DBr3+q4dS64rYpDIF3hOzJe5M7jfgu4Tr41FIPyK3ZcQTY4LFEqGYzPSZIbp0Ed0IN1a ezJw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763413786; x=1764018586; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=X5YC9CjG2cnLhN4+Emrv86sQuYMgj2JFxcP4g4fQZXE=; b=tqjbWulUXQvcbbHJfRGlSQZiLWgbSKZCNGQnWGicirNbROAEOb2ofTRJEkKLk0GO9H Cs6IzNkXDo/SBCha+5sjDaqRc/BjwytewsWmSw+e6MbCrb6U1RQFr0ZEyo+fzd9+iQKj oyzIYUuxMKARcVfQ5PjD9VI8POScsYpePjoF9epeFK6JiyXsl0d1l+53H+kQmcLQAArR nIH8JPB3ORYbljG/m18D1dVF7VrydurNt9dbhVI3fieZ+aYf4FyKQVeLVgLrWxUvawDK CNdbJXOg0w6OqdFJhoHl5/eQjx4+XvlDkeuInZYzIsfMgABgzBnbeUMlwDeJEWpEIDKa 8sYA== X-Forwarded-Encrypted: i=1; AJvYcCWDi7Oi4B/sNw+rLcYtSXE8lbyrbZf21ivt3iKesW16JYc6xxe1RZqI1c+ydybh+RGQymIfP60K2+rfbeVd@postgresql.org X-Gm-Message-State: AOJu0Yz5qRrWtosGCzREghAimaeT/AxhqYQrxw6bFHsCqfAyFbOmIXHe xDzrv/00aHZ03PFjhXWTZh3OQdb8UwJbq9HQre73dF2NALgTU/P4rD4he3MOuK+KelIhmXPHmyD b2CkyBaXblrfoMyWJnmsaRz+AwCLcnrV60w== X-Gm-Gg: ASbGncsgTU5uYTiL2XlpKpXgU0ytrS8Ri88SW8gocb9465mdd+hqVwD/SWOAs8VNbhA 6nybE9irwkAoa8G6NTjyLFP6CCDg+jtaLtYq7sFVSvNhYqFq+3EfjtxDAPeADOXu4lGSlVbTpcy HXp5qS7lItI5O9WeWQFvYcg7Hx0VAHt4zOn62qpG3DEdx31/yOiPSVGTOYeAefUbD/as1qU7zHz 91FCIl+toH2mtp8m3OeBeeOsGKEZ7hbOuB2hloRjr7MySQvvbz8hz8wuz2/8PUO+Xm7ZmSjWw== X-Google-Smtp-Source: AGHT+IGzMrGKCSr2DOyUGNLeg1jSpuSuH7EsJMrVRoSGax9MaZ9zHdm95RLVGJzFM52dxZve92jyxA1U00kBwElIcGk= X-Received: by 2002:a05:6102:4b89:b0:5df:b085:835a with SMTP id ada2fe7eead31-5dfc5b9e6d5mr4215718137.30.1763413786031; Mon, 17 Nov 2025 13:09:46 -0800 (PST) MIME-Version: 1.0 References: <59be194c5a409fb9fc9f2031581b8a44@postgrespro.ru> <764dd8b8-6374-4f5a-aac7-d8e3f6ebe5fd@postgrespro.ru> <159b591411bb2c81332018927acbd509@postgrespro.ru> <2fb1d9923b6995492e7b163e6cb95402@postgrespro.ru> In-Reply-To: From: Matheus Alcantara Date: Mon, 17 Nov 2025 18:09:19 -0300 X-Gm-Features: AWmQ_bnfbL1tZFZaXuqNwYJ9KXcrewm5X54U4Vl2SdS84arCVCdbLfpbasI-ZWc Message-ID: Subject: Re: Asynchronous MergeAppend To: Alexander Pyhalov Cc: Alena Rybakina , Pgsql Hackers Content-Type: text/plain; charset="UTF-8" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Sat Nov 15, 2025 at 7:57 AM -03, Alexander Pyhalov wrote: >> Here are some comments on my first look at the patches. I still don't >> have too much experience with the executor code but I hope that I can >> help with something. >> >> v5-0001-mark_async_capable-subpath-should-match-subplan.patch >> >> I don't have to much comments on this, perhaps we could have a commit >> message explaining the reason behind the change. > > I've expanded commit message. The issue is that mark_async_capable() > relies > on the fact that plan node type corresponds to path type. This is not > true when > (Merge)Append decides to insert Sort node. > Your explanation about why this change is needed that you've include on your first email sounds more clear IMHO. I would suggest the following for a commit message: mark_async_capable() believes that path corresponds to plan. This is not true when create_[merge_]append_plan() inserts sort node. In this case mark_async_capable() can treat Sort plan node as some other and crash. Fix this by handling the Sort node separately. This is needed to make MergeAppend node async-capable that it will be implemented in a next commit. What do you think? I was reading the patch changes again and I have a minor point: SubqueryScan *scan_plan = (SubqueryScan *) plan; /* - * If the generated plan node includes a gating Result node, - * we can't execute it asynchronously. + * If the generated plan node includes a gating Result node or + * a Sort node, we can't execute it asynchronously. */ - if (IsA(plan, Result)) + if (IsA(plan, Result) || IsA(plan, Sort)) Shouldn't we cast the plan to SubqueryScan* after the IsA(...) check? I know this code has been before your changes but type casting before a IsA() check sounds a bit strange to me. Also perhaps we could add an Assert(IsA(plan, SubqueryScan)) after the IsA(...) check and before the type casting just for sanity? >> ---- >> >> v5-0002-MergeAppend-should-support-Async-Foreign-Scan-sub.patch >> >> The AppendState struct has the "as_syncdone", this field is not needed >> on MergeAppendState? > > We don't need as_syncdone. Async Append fetches tuple from async subplan > and waits for them either when they have some data or when there's no > more sync subplans (as we can return any tuple we receive from > subplans). But ExecMergeAppend should decide which tuple to return based > on sort order, so there's no need to remember if we are done with sync > subplans, as subplans ordering matters, and we can't arbitrary switch > between them. > Ok, thanks for the explanation. > >> Regarding the duplicated code on classify_matching_subplans I think >> that >> we can have a more generic function that operates over function >> parameters > > I've tried to do so, but there are two issues. There's no suitable > common header between > nodAppend and nodeMergeAppend. I've put > classify_matching_subplans_common() into src/include/nodes/execnodes.h > and sure that it's not the best choice. The second issue is with > as_syncdone, it exists only in AppendState, so > we should check for empty valid_subplans separately. In fact, there's 3 > outcomes for Append 1) no sync plans, > no async plans, 2) no async plans, 3) async plans present, and only > last two states have meaning > for MergeAppend. > I think that's ok to have these separated checks on nodeAppend.c and nodeMergeAppend.c once the majority of duplicated steps that would be required is centralized into a single reusable function. I also agree that execnodes.h may not be the best place to declare this function but I also don't have too many ideas of where to put it. Let's see if we have more comments on this. >> ---- >> We have some reduction of code coverage on nodeMergeAppend.c. The >> significant blocks are on ExecMergeAppendAsyncBegin(): >> + /* If we've yet to determine the valid subplans then do so now. */ >> + if (!node->ms_valid_subplans_identified) >> + { >> + node->ms_valid_subplans = >> + ExecFindMatchingSubPlans(node->ms_prune_state, false, NULL); >> + node->ms_valid_subplans_identified = true; >> + >> + classify_matching_subplans(node); >> + } >> >> And there are some blocks on ExecReScanMergeAppend(). It's worth adding >> a test case for then? I'm not sure how hard would be to write a >> regression test that cover these blocks. >> > > You are right. There's difference between ExecAppend and > ExecMergeAppend. Append identifies valid subplans in > ExecAppendAsyncBegin. MergeAppend - earlier, in ExecMergeAppend(). So > this is really the dead code. And there was an issue with it, which > became evident when I've added test for rescan. When we've identified > new subplans in ExecMergeAppend(), we have to classify them. > Thanks, the code coverage looks better now. I plan to do another round of review on 0002, in the meantime I'm sharing these comments for now. -- Matheus Alcantara EDB: http://www.enterprisedb.com