From b85289b511ed8242f08e83d8132070eb0a64d9be Mon Sep 17 00:00:00 2001
From: Yuya Watari <watari.yuya@gmail.com>
Date: Thu, 20 Oct 2022 15:46:00 +0900
Subject: [PATCH v9 3/4] Use conventional algorithm for smaller size cases

---
 src/backend/optimizer/path/pathkeys.c | 58 ++++++++++++++++++++++-----
 1 file changed, 49 insertions(+), 9 deletions(-)

diff --git a/src/backend/optimizer/path/pathkeys.c b/src/backend/optimizer/path/pathkeys.c
index be11e1c053..8426d2681a 100644
--- a/src/backend/optimizer/path/pathkeys.c
+++ b/src/backend/optimizer/path/pathkeys.c
@@ -1434,9 +1434,6 @@ select_outer_pathkeys_for_merge(PlannerInfo *root,
 	{
 		RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
 		EquivalenceClass *oeclass;
-		Bitmapset		 *matching_ems;
-		Bitmapset		 *interesting_ems;
-		Bitmapset		 *other_parent_ems;
 
 		/* get the outer eclass */
 		update_mergeclause_eclasses(root, rinfo);
@@ -1455,14 +1452,57 @@ select_outer_pathkeys_for_merge(PlannerInfo *root,
 		if (j < necs)
 			continue;
 
-		/* compute score */
-		matching_ems = get_ecmember_indexes(root, oeclass, joinrel->relids, false, false);
-		other_parent_ems = bms_difference(oeclass->ec_nonchild_indexes, oeclass->ec_norel_indexes);
-		interesting_ems = bms_difference(other_parent_ems, matching_ems);
+		/* Compute score */
+		/*
+		 * We use two different algorithms depending on the size of the
+		 * problem. For small sizes, linear search is preferable, while
+		 * optimization based on bitmap sets is faster for larger sizes.
+		 */
+		/*
+		 * TODO: Switching two algorithms is not ideal and may be ugly
+		 * because it introduces code duplication. Is there a better way?
+		 */
+		/*
+		 * TODO: 32 is a magic number. Do we have to declare it as a constant
+		 * macro?
+		 */
+		if (root->simple_rel_array_size < 32)
+		{
+			int			score;
+			int			k;
+
+			/* compute score */
+			score = 0;
+			k = -1;
+			while ((k = bms_next_member(oeclass->ec_member_indexes, k)) >= 0)
+			{
+				EquivalenceMember *em = list_nth_node(EquivalenceMember,
+													  root->eq_members, k);
+
+				/* Potential future join partner? */
+				if (!em->em_is_const && !em->em_is_child &&
+					!bms_overlap(em->em_relids, joinrel->relids))
+					score++;
+			}
+
+			scores[necs] = score;
+		}
+		else
+		{
+			Bitmapset		 *matching_ems;
+			Bitmapset		 *interesting_ems;
+			Bitmapset		 *other_parent_ems;
+
+			/* compute score */
+			matching_ems = get_ecmember_indexes(root, oeclass, joinrel->relids, false, false);
+			other_parent_ems = bms_difference(oeclass->ec_nonchild_indexes, oeclass->ec_norel_indexes);
+			interesting_ems = bms_difference(other_parent_ems, matching_ems);
+
+			/* record results */
+			scores[necs] = bms_num_members(interesting_ems);
+		}
 
-		/* record results */
 		ecs[necs] = oeclass;
-		scores[necs] = bms_num_members(interesting_ems);
 		necs++;
 	}
 
-- 
2.35.3.windows.1

