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 1vuqqL-009faR-27 for pgsql-hackers@arkaria.postgresql.org; Tue, 24 Feb 2026 11:44:45 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vuqqJ-000wO0-0r for pgsql-hackers@arkaria.postgresql.org; Tue, 24 Feb 2026 11:44:43 +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.96) (envelope-from ) id 1vuqqI-000wNq-2G for pgsql-hackers@lists.postgresql.org; Tue, 24 Feb 2026 11:44:42 +0000 Received: from meldrar.postgresql.org ([2a02:c0:301:0:ffff::31]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1vuqqF-000000012iC-0Hjb for pgsql-hackers@postgresql.org; Tue, 24 Feb 2026 11:44:42 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=postgresql.org; s=20171124; h=Content-Transfer-Encoding:Content-Type: Mime-Version:References:In-Reply-To:From:Subject:Cc:To:Message-Id:Date:Sender :Reply-To:Content-ID:Content-Description; bh=TOJ1vvmLurZXEr3MDxxHwWleAfNJCOtBS7T+G0P5zRE=; b=gU7HEJxaBlCh3PilnflosJGDqM GRYBp2uIkHyOP+maayeteA2ol4r5ktC20RL1Ap/JwMIi54Zv+2KnmxOwh4FsXHNG2990iaJBqcoUC YFBAlokQ6xP7++TLrAZ1v02LcE8D5jazTavPkUsn5a/qYyrhy8GFU0iZ3TK5tRZUSUaK5jgGHfMkD YOx51mM7eBQYqamEHUaJiTGK6mWZGtlpdivLmBY7pzcPl1qQA2DaVWGIpygZ/Y9v73RooMeBcWJox G+YG103xQkpOifjJf9/9+Scs5XDOsqui1T9q8+G2j26JcN0dWj4ThJZCi5Tahd+rlQx/DDRpzHMJV v58U2r9w==; Received: from [2409:11:4120:300:e34c:3bd3:1454:b1b6] (helo=localhost) by meldrar.postgresql.org with esmtpsa (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vuqq6-002Ivk-1H; Tue, 24 Feb 2026 11:44:35 +0000 Date: Tue, 24 Feb 2026 20:44:17 +0900 (JST) Message-Id: <20260224.204417.914253025244188300.ishii@postgresql.org> To: assam258@gmail.com Cc: vik@postgresfriends.org, er@xs4all.nl, jacob.champion@enterprisedb.com, david.g.johnston@gmail.com, peter@eisentraut.org, pgsql-hackers@postgresql.org Subject: Re: Row pattern recognition From: Tatsuo Ishii In-Reply-To: <20260224.140927.1828965853586507533.ishii@postgresql.org> References: <20260224.115625.1966558814200895991.ishii@postgresql.org> <20260224.140927.1828965853586507533.ishii@postgresql.org> X-Mailer: Mew version 6.8 on Emacs 29.3 Mime-Version: 1.0 Content-Type: Multipart/Mixed; boundary="--Next_Part(Tue_Feb_24_20_44_17_2026_043)--" Content-Transfer-Encoding: 7bit X-Host-Lookup-Failed: Reverse DNS lookup failed for 2409:11:4120:300:e34c:3bd3:1454:b1b6 (failed) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk ----Next_Part(Tue_Feb_24_20_44_17_2026_043)-- Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit Hi Henson, Currently we do not account the cost of RPR while planning. Attached is the first attempt to try to estimate the RPR costs. The cost model is very simple: expression cost per PATTERN variable * number of input tuples Any idea to make this estimation better? Best regards, -- Tatsuo Ishii SRA OSS K.K. English: http://www.sraoss.co.jp/index_en/ Japanese:http://www.sraoss.co.jp ----Next_Part(Tue_Feb_24_20_44_17_2026_043)-- Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="cost_rpr.txt" diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index 89ca4e08bf1..5a221214b21 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -103,6 +103,7 @@ #include "optimizer/placeholder.h" #include "optimizer/plancat.h" #include "optimizer/restrictinfo.h" +#include "optimizer/rpr.h" #include "parser/parsetree.h" #include "utils/lsyscache.h" #include "utils/selfuncs.h" @@ -3227,12 +3228,16 @@ cost_windowagg(Path *path, PlannerInfo *root, * many rows the window function will fetch, it's hard to do better. In * any case, it's a good estimate for all the built-in window functions, * so we'll just do this for now. + * + * Moreover, if DEFINE/PATTERN clause exists, we charge their expressions + * per tuple. */ foreach(lc, windowFuncs) { WindowFunc *wfunc = lfirst_node(WindowFunc, lc); Cost wfunccost; QualCost argcosts; + QualCost defcosts; argcosts.startup = argcosts.per_tuple = 0; add_function_cost(root, wfunc->winfnoid, (Node *) wfunc, @@ -3245,6 +3250,37 @@ cost_windowagg(Path *path, PlannerInfo *root, startup_cost += argcosts.startup; wfunccost += argcosts.per_tuple; + /* also add DEFINE clause expressions' cost to per-input-row costs */ + if (winclause->rpPattern) + { + List *pattern_vars; /* list of pattern variable names */ + ListCell *lc2; + + pattern_vars = collectPatternVariables(winclause->rpPattern); + + /* iterate according to the pattern variable */ + foreach(lc2, pattern_vars) + { + char *ptname = strVal((char *) lfirst(lc2)); + + /* iterate according to the DEFINE clause */ + foreach_node(TargetEntry, def, winclause->defineClause) + { + if (!strcmp(ptname, def->resname)) + { + /* + * varname found. Add DEFINE clause expressions' cost + * to per-input-row costs. + */ + cost_qual_eval_node(&defcosts, (Node *) def->expr, root); + startup_cost += defcosts.startup; + wfunccost += defcosts.per_tuple; + } + } + } + list_free_deep(pattern_vars); + } + /* * Add the filter's cost to per-input-row costs. XXX We should reduce * input expression costs according to filter selectivity. ----Next_Part(Tue_Feb_24_20_44_17_2026_043)----