From ca3d14f2a98b49d989090c800835b80087286cb4 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sat, 21 Apr 2007 02:41:13 +0000
Subject: [PATCH] Tweak set_rel_width() to avoid redundant executions of
 getrelid(). In very large queries this accounts for a noticeable fraction of
 planning time.  Per an example from Greg Stark.

---
 src/backend/optimizer/path/costsize.c | 24 +++++++++++++++++++-----
 1 file changed, 19 insertions(+), 5 deletions(-)

diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index ff5bb783372..42a5520b974 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -54,7 +54,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.179 2007/03/27 23:21:09 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.180 2007/04/21 02:41:13 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2357,12 +2357,22 @@ set_rel_width(PlannerInfo *root, RelOptInfo *rel)
 {
 	int32		tuple_width = 0;
 	ListCell   *tllist;
+	Oid			rel_reloid;
+
+	/*
+	 * Usually (perhaps always), all the Vars have the same reloid, so we can
+	 * save some redundant list-searching by doing getrelid just once.
+	 */
+	if (rel->relid > 0)
+		rel_reloid = getrelid(rel->relid, root->parse->rtable);
+	else
+		rel_reloid = InvalidOid;			/* probably can't happen */
 
 	foreach(tllist, rel->reltargetlist)
 	{
 		Var		   *var = (Var *) lfirst(tllist);
 		int			ndx;
-		Oid			relid;
+		Oid			var_reloid;
 		int32		item_width;
 
 		/* For now, punt on whole-row child Vars */
@@ -2383,10 +2393,14 @@ set_rel_width(PlannerInfo *root, RelOptInfo *rel)
 			continue;
 		}
 
-		relid = getrelid(var->varno, root->parse->rtable);
-		if (relid != InvalidOid)
+		if (var->varno == rel->relid)
+			var_reloid = rel_reloid;
+		else
+			var_reloid = getrelid(var->varno, root->parse->rtable);
+
+		if (var_reloid != InvalidOid)
 		{
-			item_width = get_attavgwidth(relid, var->varattno);
+			item_width = get_attavgwidth(var_reloid, var->varattno);
 			if (item_width > 0)
 			{
 				rel->attr_widths[ndx] = item_width;
-- 
GitLab