mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-04 00:02:52 -05:00 
			
		
		
		
	Track the number of presorted outer pathkeys in MergePath
When creating an explicit Sort node for the outer path of a mergejoin, we need to determine the number of presorted keys of the outer path to decide whether explicit incremental sort can be applied. Currently, this is done by repeatedly calling pathkeys_count_contained_in. This patch caches the number of presorted outer pathkeys in MergePath, allowing us to save several calls to pathkeys_count_contained_in. It can be considered a complement to the changes in commit 828e94c9d. Reported-by: David Rowley <dgrowleyml@gmail.com> Author: Richard Guo <guofenglinux@gmail.com> Reviewed-by: Tender Wang <tndrwang@gmail.com> Discussion: https://postgr.es/m/CAApHDvqvBireB_w6x8BN5txdvBEHxVgZBt=rUnpf5ww5P_E_ww@mail.gmail.com
This commit is contained in:
		
							parent
							
								
									773db22269
								
							
						
					
					
						commit
						c06e909c26
					
				@ -821,8 +821,9 @@ GetExistingLocalJoinPath(RelOptInfo *joinrel)
 | 
				
			|||||||
					 * for the mergejoin, we can skip doing an explicit sort.
 | 
										 * for the mergejoin, we can skip doing an explicit sort.
 | 
				
			||||||
					 */
 | 
										 */
 | 
				
			||||||
					if (merge_path->outersortkeys &&
 | 
										if (merge_path->outersortkeys &&
 | 
				
			||||||
						pathkeys_contained_in(merge_path->outersortkeys,
 | 
											pathkeys_count_contained_in(merge_path->outersortkeys,
 | 
				
			||||||
											  joinpath->outerjoinpath->pathkeys))
 | 
																		joinpath->outerjoinpath->pathkeys,
 | 
				
			||||||
 | 
																		&merge_path->outer_presorted_keys))
 | 
				
			||||||
						merge_path->outersortkeys = NIL;
 | 
											merge_path->outersortkeys = NIL;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
				
			|||||||
@ -3542,6 +3542,7 @@ final_cost_nestloop(PlannerInfo *root, NestPath *path,
 | 
				
			|||||||
 * 'inner_path' is the inner input to the join
 | 
					 * 'inner_path' is the inner input to the join
 | 
				
			||||||
 * 'outersortkeys' is the list of sort keys for the outer path
 | 
					 * 'outersortkeys' is the list of sort keys for the outer path
 | 
				
			||||||
 * 'innersortkeys' is the list of sort keys for the inner path
 | 
					 * 'innersortkeys' is the list of sort keys for the inner path
 | 
				
			||||||
 | 
					 * 'outer_presorted_keys' is the number of presorted keys of the outer path
 | 
				
			||||||
 * 'extra' contains miscellaneous information about the join
 | 
					 * 'extra' contains miscellaneous information about the join
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Note: outersortkeys and innersortkeys should be NIL if no explicit
 | 
					 * Note: outersortkeys and innersortkeys should be NIL if no explicit
 | 
				
			||||||
@ -3553,6 +3554,7 @@ initial_cost_mergejoin(PlannerInfo *root, JoinCostWorkspace *workspace,
 | 
				
			|||||||
					   List *mergeclauses,
 | 
										   List *mergeclauses,
 | 
				
			||||||
					   Path *outer_path, Path *inner_path,
 | 
										   Path *outer_path, Path *inner_path,
 | 
				
			||||||
					   List *outersortkeys, List *innersortkeys,
 | 
										   List *outersortkeys, List *innersortkeys,
 | 
				
			||||||
 | 
										   int outer_presorted_keys,
 | 
				
			||||||
					   JoinPathExtraData *extra)
 | 
										   JoinPathExtraData *extra)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int			disabled_nodes;
 | 
						int			disabled_nodes;
 | 
				
			||||||
@ -3683,27 +3685,33 @@ initial_cost_mergejoin(PlannerInfo *root, JoinCostWorkspace *workspace,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	if (outersortkeys)			/* do we need to sort outer? */
 | 
						if (outersortkeys)			/* do we need to sort outer? */
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		bool		use_incremental_sort = false;
 | 
							/*
 | 
				
			||||||
		int			presorted_keys;
 | 
							 * We can assert that the outer path is not already ordered
 | 
				
			||||||
 | 
							 * appropriately for the mergejoin; otherwise, outersortkeys would
 | 
				
			||||||
 | 
							 * have been set to NIL.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							Assert(!pathkeys_contained_in(outersortkeys, outer_path->pathkeys));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * We choose to use incremental sort if it is enabled and there are
 | 
							 * We choose to use incremental sort if it is enabled and there are
 | 
				
			||||||
		 * presorted keys; otherwise we use full sort.
 | 
							 * presorted keys; otherwise we use full sort.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		if (enable_incremental_sort)
 | 
							if (enable_incremental_sort && outer_presorted_keys > 0)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			bool		is_sorted PG_USED_FOR_ASSERTS_ONLY;
 | 
								cost_incremental_sort(&sort_path,
 | 
				
			||||||
 | 
													  root,
 | 
				
			||||||
			is_sorted = pathkeys_count_contained_in(outersortkeys,
 | 
													  outersortkeys,
 | 
				
			||||||
													outer_path->pathkeys,
 | 
													  outer_presorted_keys,
 | 
				
			||||||
													&presorted_keys);
 | 
													  outer_path->disabled_nodes,
 | 
				
			||||||
			Assert(!is_sorted);
 | 
													  outer_path->startup_cost,
 | 
				
			||||||
 | 
													  outer_path->total_cost,
 | 
				
			||||||
			if (presorted_keys > 0)
 | 
													  outer_path_rows,
 | 
				
			||||||
				use_incremental_sort = true;
 | 
													  outer_path->pathtarget->width,
 | 
				
			||||||
 | 
													  0.0,
 | 
				
			||||||
 | 
													  work_mem,
 | 
				
			||||||
 | 
													  -1.0);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
		if (!use_incremental_sort)
 | 
					 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			cost_sort(&sort_path,
 | 
								cost_sort(&sort_path,
 | 
				
			||||||
					  root,
 | 
										  root,
 | 
				
			||||||
@ -3716,21 +3724,7 @@ initial_cost_mergejoin(PlannerInfo *root, JoinCostWorkspace *workspace,
 | 
				
			|||||||
					  work_mem,
 | 
										  work_mem,
 | 
				
			||||||
					  -1.0);
 | 
										  -1.0);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else
 | 
					
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			cost_incremental_sort(&sort_path,
 | 
					 | 
				
			||||||
								  root,
 | 
					 | 
				
			||||||
								  outersortkeys,
 | 
					 | 
				
			||||||
								  presorted_keys,
 | 
					 | 
				
			||||||
								  outer_path->disabled_nodes,
 | 
					 | 
				
			||||||
								  outer_path->startup_cost,
 | 
					 | 
				
			||||||
								  outer_path->total_cost,
 | 
					 | 
				
			||||||
								  outer_path_rows,
 | 
					 | 
				
			||||||
								  outer_path->pathtarget->width,
 | 
					 | 
				
			||||||
								  0.0,
 | 
					 | 
				
			||||||
								  work_mem,
 | 
					 | 
				
			||||||
								  -1.0);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		disabled_nodes += sort_path.disabled_nodes;
 | 
							disabled_nodes += sort_path.disabled_nodes;
 | 
				
			||||||
		startup_cost += sort_path.startup_cost;
 | 
							startup_cost += sort_path.startup_cost;
 | 
				
			||||||
		startup_cost += (sort_path.total_cost - sort_path.startup_cost)
 | 
							startup_cost += (sort_path.total_cost - sort_path.startup_cost)
 | 
				
			||||||
@ -3750,6 +3744,13 @@ initial_cost_mergejoin(PlannerInfo *root, JoinCostWorkspace *workspace,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	if (innersortkeys)			/* do we need to sort inner? */
 | 
						if (innersortkeys)			/* do we need to sort inner? */
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * We can assert that the inner path is not already ordered
 | 
				
			||||||
 | 
							 * appropriately for the mergejoin; otherwise, innersortkeys would
 | 
				
			||||||
 | 
							 * have been set to NIL.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							Assert(!pathkeys_contained_in(innersortkeys, inner_path->pathkeys));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * We do not consider incremental sort for inner path, because
 | 
							 * We do not consider incremental sort for inner path, because
 | 
				
			||||||
		 * incremental sort does not support mark/restore.
 | 
							 * incremental sort does not support mark/restore.
 | 
				
			||||||
 | 
				
			|||||||
@ -1042,6 +1042,7 @@ try_mergejoin_path(PlannerInfo *root,
 | 
				
			|||||||
				   bool is_partial)
 | 
									   bool is_partial)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	Relids		required_outer;
 | 
						Relids		required_outer;
 | 
				
			||||||
 | 
						int			outer_presorted_keys = 0;
 | 
				
			||||||
	JoinCostWorkspace workspace;
 | 
						JoinCostWorkspace workspace;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (is_partial)
 | 
						if (is_partial)
 | 
				
			||||||
@ -1087,9 +1088,16 @@ try_mergejoin_path(PlannerInfo *root,
 | 
				
			|||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * If the given paths are already well enough ordered, we can skip doing
 | 
						 * If the given paths are already well enough ordered, we can skip doing
 | 
				
			||||||
	 * an explicit sort.
 | 
						 * an explicit sort.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * We need to determine the number of presorted keys of the outer path to
 | 
				
			||||||
 | 
						 * decide whether explicit incremental sort can be applied when
 | 
				
			||||||
 | 
						 * outersortkeys is not NIL.  We do not need to do the same for the inner
 | 
				
			||||||
 | 
						 * path though, as incremental sort currently does not support
 | 
				
			||||||
 | 
						 * mark/restore.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (outersortkeys &&
 | 
						if (outersortkeys &&
 | 
				
			||||||
		pathkeys_contained_in(outersortkeys, outer_path->pathkeys))
 | 
							pathkeys_count_contained_in(outersortkeys, outer_path->pathkeys,
 | 
				
			||||||
 | 
														&outer_presorted_keys))
 | 
				
			||||||
		outersortkeys = NIL;
 | 
							outersortkeys = NIL;
 | 
				
			||||||
	if (innersortkeys &&
 | 
						if (innersortkeys &&
 | 
				
			||||||
		pathkeys_contained_in(innersortkeys, inner_path->pathkeys))
 | 
							pathkeys_contained_in(innersortkeys, inner_path->pathkeys))
 | 
				
			||||||
@ -1101,6 +1109,7 @@ try_mergejoin_path(PlannerInfo *root,
 | 
				
			|||||||
	initial_cost_mergejoin(root, &workspace, jointype, mergeclauses,
 | 
						initial_cost_mergejoin(root, &workspace, jointype, mergeclauses,
 | 
				
			||||||
						   outer_path, inner_path,
 | 
											   outer_path, inner_path,
 | 
				
			||||||
						   outersortkeys, innersortkeys,
 | 
											   outersortkeys, innersortkeys,
 | 
				
			||||||
 | 
											   outer_presorted_keys,
 | 
				
			||||||
						   extra);
 | 
											   extra);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (add_path_precheck(joinrel, workspace.disabled_nodes,
 | 
						if (add_path_precheck(joinrel, workspace.disabled_nodes,
 | 
				
			||||||
@ -1120,7 +1129,8 @@ try_mergejoin_path(PlannerInfo *root,
 | 
				
			|||||||
									   required_outer,
 | 
														   required_outer,
 | 
				
			||||||
									   mergeclauses,
 | 
														   mergeclauses,
 | 
				
			||||||
									   outersortkeys,
 | 
														   outersortkeys,
 | 
				
			||||||
									   innersortkeys));
 | 
														   innersortkeys,
 | 
				
			||||||
 | 
														   outer_presorted_keys));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@ -1146,6 +1156,7 @@ try_partial_mergejoin_path(PlannerInfo *root,
 | 
				
			|||||||
						   JoinType jointype,
 | 
											   JoinType jointype,
 | 
				
			||||||
						   JoinPathExtraData *extra)
 | 
											   JoinPathExtraData *extra)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						int			outer_presorted_keys = 0;
 | 
				
			||||||
	JoinCostWorkspace workspace;
 | 
						JoinCostWorkspace workspace;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
@ -1159,9 +1170,16 @@ try_partial_mergejoin_path(PlannerInfo *root,
 | 
				
			|||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * If the given paths are already well enough ordered, we can skip doing
 | 
						 * If the given paths are already well enough ordered, we can skip doing
 | 
				
			||||||
	 * an explicit sort.
 | 
						 * an explicit sort.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * We need to determine the number of presorted keys of the outer path to
 | 
				
			||||||
 | 
						 * decide whether explicit incremental sort can be applied when
 | 
				
			||||||
 | 
						 * outersortkeys is not NIL.  We do not need to do the same for the inner
 | 
				
			||||||
 | 
						 * path though, as incremental sort currently does not support
 | 
				
			||||||
 | 
						 * mark/restore.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (outersortkeys &&
 | 
						if (outersortkeys &&
 | 
				
			||||||
		pathkeys_contained_in(outersortkeys, outer_path->pathkeys))
 | 
							pathkeys_count_contained_in(outersortkeys, outer_path->pathkeys,
 | 
				
			||||||
 | 
														&outer_presorted_keys))
 | 
				
			||||||
		outersortkeys = NIL;
 | 
							outersortkeys = NIL;
 | 
				
			||||||
	if (innersortkeys &&
 | 
						if (innersortkeys &&
 | 
				
			||||||
		pathkeys_contained_in(innersortkeys, inner_path->pathkeys))
 | 
							pathkeys_contained_in(innersortkeys, inner_path->pathkeys))
 | 
				
			||||||
@ -1173,6 +1191,7 @@ try_partial_mergejoin_path(PlannerInfo *root,
 | 
				
			|||||||
	initial_cost_mergejoin(root, &workspace, jointype, mergeclauses,
 | 
						initial_cost_mergejoin(root, &workspace, jointype, mergeclauses,
 | 
				
			||||||
						   outer_path, inner_path,
 | 
											   outer_path, inner_path,
 | 
				
			||||||
						   outersortkeys, innersortkeys,
 | 
											   outersortkeys, innersortkeys,
 | 
				
			||||||
 | 
											   outer_presorted_keys,
 | 
				
			||||||
						   extra);
 | 
											   extra);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!add_partial_path_precheck(joinrel, workspace.disabled_nodes,
 | 
						if (!add_partial_path_precheck(joinrel, workspace.disabled_nodes,
 | 
				
			||||||
@ -1193,7 +1212,8 @@ try_partial_mergejoin_path(PlannerInfo *root,
 | 
				
			|||||||
										   NULL,
 | 
															   NULL,
 | 
				
			||||||
										   mergeclauses,
 | 
															   mergeclauses,
 | 
				
			||||||
										   outersortkeys,
 | 
															   outersortkeys,
 | 
				
			||||||
										   innersortkeys));
 | 
															   innersortkeys,
 | 
				
			||||||
 | 
															   outer_presorted_keys));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 | 
				
			|||||||
@ -4521,27 +4521,33 @@ create_mergejoin_plan(PlannerInfo *root,
 | 
				
			|||||||
	{
 | 
						{
 | 
				
			||||||
		Relids		outer_relids = outer_path->parent->relids;
 | 
							Relids		outer_relids = outer_path->parent->relids;
 | 
				
			||||||
		Plan	   *sort_plan;
 | 
							Plan	   *sort_plan;
 | 
				
			||||||
		bool		use_incremental_sort = false;
 | 
					
 | 
				
			||||||
		int			presorted_keys;
 | 
							/*
 | 
				
			||||||
 | 
							 * We can assert that the outer path is not already ordered
 | 
				
			||||||
 | 
							 * appropriately for the mergejoin; otherwise, outersortkeys would
 | 
				
			||||||
 | 
							 * have been set to NIL.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							Assert(!pathkeys_contained_in(best_path->outersortkeys,
 | 
				
			||||||
 | 
														  outer_path->pathkeys));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * We choose to use incremental sort if it is enabled and there are
 | 
							 * We choose to use incremental sort if it is enabled and there are
 | 
				
			||||||
		 * presorted keys; otherwise we use full sort.
 | 
							 * presorted keys; otherwise we use full sort.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		if (enable_incremental_sort)
 | 
							if (enable_incremental_sort && best_path->outer_presorted_keys > 0)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			bool		is_sorted PG_USED_FOR_ASSERTS_ONLY;
 | 
								sort_plan = (Plan *)
 | 
				
			||||||
 | 
									make_incrementalsort_from_pathkeys(outer_plan,
 | 
				
			||||||
 | 
																	   best_path->outersortkeys,
 | 
				
			||||||
 | 
																	   outer_relids,
 | 
				
			||||||
 | 
																	   best_path->outer_presorted_keys);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			is_sorted = pathkeys_count_contained_in(best_path->outersortkeys,
 | 
								label_incrementalsort_with_costsize(root,
 | 
				
			||||||
													outer_path->pathkeys,
 | 
																	(IncrementalSort *) sort_plan,
 | 
				
			||||||
													&presorted_keys);
 | 
																	best_path->outersortkeys,
 | 
				
			||||||
			Assert(!is_sorted);
 | 
																	-1.0);
 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (presorted_keys > 0)
 | 
					 | 
				
			||||||
				use_incremental_sort = true;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
		if (!use_incremental_sort)
 | 
					 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			sort_plan = (Plan *)
 | 
								sort_plan = (Plan *)
 | 
				
			||||||
				make_sort_from_pathkeys(outer_plan,
 | 
									make_sort_from_pathkeys(outer_plan,
 | 
				
			||||||
@ -4550,19 +4556,6 @@ create_mergejoin_plan(PlannerInfo *root,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			label_sort_with_costsize(root, (Sort *) sort_plan, -1.0);
 | 
								label_sort_with_costsize(root, (Sort *) sort_plan, -1.0);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			sort_plan = (Plan *)
 | 
					 | 
				
			||||||
				make_incrementalsort_from_pathkeys(outer_plan,
 | 
					 | 
				
			||||||
												   best_path->outersortkeys,
 | 
					 | 
				
			||||||
												   outer_relids,
 | 
					 | 
				
			||||||
												   presorted_keys);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			label_incrementalsort_with_costsize(root,
 | 
					 | 
				
			||||||
												(IncrementalSort *) sort_plan,
 | 
					 | 
				
			||||||
												best_path->outersortkeys,
 | 
					 | 
				
			||||||
												-1.0);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		outer_plan = sort_plan;
 | 
							outer_plan = sort_plan;
 | 
				
			||||||
		outerpathkeys = best_path->outersortkeys;
 | 
							outerpathkeys = best_path->outersortkeys;
 | 
				
			||||||
@ -4578,9 +4571,19 @@ create_mergejoin_plan(PlannerInfo *root,
 | 
				
			|||||||
		 */
 | 
							 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Relids		inner_relids = inner_path->parent->relids;
 | 
							Relids		inner_relids = inner_path->parent->relids;
 | 
				
			||||||
		Sort	   *sort = make_sort_from_pathkeys(inner_plan,
 | 
							Sort	   *sort;
 | 
				
			||||||
												   best_path->innersortkeys,
 | 
					
 | 
				
			||||||
												   inner_relids);
 | 
							/*
 | 
				
			||||||
 | 
							 * We can assert that the inner path is not already ordered
 | 
				
			||||||
 | 
							 * appropriately for the mergejoin; otherwise, innersortkeys would
 | 
				
			||||||
 | 
							 * have been set to NIL.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							Assert(!pathkeys_contained_in(best_path->innersortkeys,
 | 
				
			||||||
 | 
														  inner_path->pathkeys));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sort = make_sort_from_pathkeys(inner_plan,
 | 
				
			||||||
 | 
														   best_path->innersortkeys,
 | 
				
			||||||
 | 
														   inner_relids);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		label_sort_with_costsize(root, sort, -1.0);
 | 
							label_sort_with_costsize(root, sort, -1.0);
 | 
				
			||||||
		inner_plan = (Plan *) sort;
 | 
							inner_plan = (Plan *) sort;
 | 
				
			||||||
 | 
				
			|||||||
@ -2626,6 +2626,7 @@ create_nestloop_path(PlannerInfo *root,
 | 
				
			|||||||
 *		(this should be a subset of the restrict_clauses list)
 | 
					 *		(this should be a subset of the restrict_clauses list)
 | 
				
			||||||
 * 'outersortkeys' are the sort varkeys for the outer relation
 | 
					 * 'outersortkeys' are the sort varkeys for the outer relation
 | 
				
			||||||
 * 'innersortkeys' are the sort varkeys for the inner relation
 | 
					 * 'innersortkeys' are the sort varkeys for the inner relation
 | 
				
			||||||
 | 
					 * 'outer_presorted_keys' is the number of presorted keys of the outer path
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
MergePath *
 | 
					MergePath *
 | 
				
			||||||
create_mergejoin_path(PlannerInfo *root,
 | 
					create_mergejoin_path(PlannerInfo *root,
 | 
				
			||||||
@ -2640,7 +2641,8 @@ create_mergejoin_path(PlannerInfo *root,
 | 
				
			|||||||
					  Relids required_outer,
 | 
										  Relids required_outer,
 | 
				
			||||||
					  List *mergeclauses,
 | 
										  List *mergeclauses,
 | 
				
			||||||
					  List *outersortkeys,
 | 
										  List *outersortkeys,
 | 
				
			||||||
					  List *innersortkeys)
 | 
										  List *innersortkeys,
 | 
				
			||||||
 | 
										  int outer_presorted_keys)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	MergePath  *pathnode = makeNode(MergePath);
 | 
						MergePath  *pathnode = makeNode(MergePath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -2669,6 +2671,7 @@ create_mergejoin_path(PlannerInfo *root,
 | 
				
			|||||||
	pathnode->path_mergeclauses = mergeclauses;
 | 
						pathnode->path_mergeclauses = mergeclauses;
 | 
				
			||||||
	pathnode->outersortkeys = outersortkeys;
 | 
						pathnode->outersortkeys = outersortkeys;
 | 
				
			||||||
	pathnode->innersortkeys = innersortkeys;
 | 
						pathnode->innersortkeys = innersortkeys;
 | 
				
			||||||
 | 
						pathnode->outer_presorted_keys = outer_presorted_keys;
 | 
				
			||||||
	/* pathnode->skip_mark_restore will be set by final_cost_mergejoin */
 | 
						/* pathnode->skip_mark_restore will be set by final_cost_mergejoin */
 | 
				
			||||||
	/* pathnode->materialize_inner will be set by final_cost_mergejoin */
 | 
						/* pathnode->materialize_inner will be set by final_cost_mergejoin */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -2253,6 +2253,12 @@ typedef struct NestPath
 | 
				
			|||||||
 * mergejoin.  If it is not NIL then it is a PathKeys list describing
 | 
					 * mergejoin.  If it is not NIL then it is a PathKeys list describing
 | 
				
			||||||
 * the ordering that must be created by an explicit Sort node.
 | 
					 * the ordering that must be created by an explicit Sort node.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * outer_presorted_keys is the number of presorted keys of the outer
 | 
				
			||||||
 | 
					 * path that match outersortkeys.  It is used to determine whether
 | 
				
			||||||
 | 
					 * explicit incremental sort can be applied when outersortkeys is not
 | 
				
			||||||
 | 
					 * NIL.  We do not track the number of presorted keys of the inner
 | 
				
			||||||
 | 
					 * path, as incremental sort currently does not support mark/restore.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 * skip_mark_restore is true if the executor need not do mark/restore calls.
 | 
					 * skip_mark_restore is true if the executor need not do mark/restore calls.
 | 
				
			||||||
 * Mark/restore overhead is usually required, but can be skipped if we know
 | 
					 * Mark/restore overhead is usually required, but can be skipped if we know
 | 
				
			||||||
 * that the executor need find only one match per outer tuple, and that the
 | 
					 * that the executor need find only one match per outer tuple, and that the
 | 
				
			||||||
@ -2270,6 +2276,8 @@ typedef struct MergePath
 | 
				
			|||||||
	List	   *path_mergeclauses;	/* join clauses to be used for merge */
 | 
						List	   *path_mergeclauses;	/* join clauses to be used for merge */
 | 
				
			||||||
	List	   *outersortkeys;	/* keys for explicit sort, if any */
 | 
						List	   *outersortkeys;	/* keys for explicit sort, if any */
 | 
				
			||||||
	List	   *innersortkeys;	/* keys for explicit sort, if any */
 | 
						List	   *innersortkeys;	/* keys for explicit sort, if any */
 | 
				
			||||||
 | 
						int			outer_presorted_keys;	/* number of presorted keys of the
 | 
				
			||||||
 | 
															 * outer path */
 | 
				
			||||||
	bool		skip_mark_restore;	/* can executor skip mark/restore? */
 | 
						bool		skip_mark_restore;	/* can executor skip mark/restore? */
 | 
				
			||||||
	bool		materialize_inner;	/* add Materialize to inner? */
 | 
						bool		materialize_inner;	/* add Materialize to inner? */
 | 
				
			||||||
} MergePath;
 | 
					} MergePath;
 | 
				
			||||||
 | 
				
			|||||||
@ -160,6 +160,7 @@ extern void initial_cost_mergejoin(PlannerInfo *root,
 | 
				
			|||||||
								   List *mergeclauses,
 | 
													   List *mergeclauses,
 | 
				
			||||||
								   Path *outer_path, Path *inner_path,
 | 
													   Path *outer_path, Path *inner_path,
 | 
				
			||||||
								   List *outersortkeys, List *innersortkeys,
 | 
													   List *outersortkeys, List *innersortkeys,
 | 
				
			||||||
 | 
													   int outer_presorted_keys,
 | 
				
			||||||
								   JoinPathExtraData *extra);
 | 
													   JoinPathExtraData *extra);
 | 
				
			||||||
extern void final_cost_mergejoin(PlannerInfo *root, MergePath *path,
 | 
					extern void final_cost_mergejoin(PlannerInfo *root, MergePath *path,
 | 
				
			||||||
								 JoinCostWorkspace *workspace,
 | 
													 JoinCostWorkspace *workspace,
 | 
				
			||||||
 | 
				
			|||||||
@ -179,7 +179,8 @@ extern MergePath *create_mergejoin_path(PlannerInfo *root,
 | 
				
			|||||||
										Relids required_outer,
 | 
															Relids required_outer,
 | 
				
			||||||
										List *mergeclauses,
 | 
															List *mergeclauses,
 | 
				
			||||||
										List *outersortkeys,
 | 
															List *outersortkeys,
 | 
				
			||||||
										List *innersortkeys);
 | 
															List *innersortkeys,
 | 
				
			||||||
 | 
															int outer_presorted_keys);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern HashPath *create_hashjoin_path(PlannerInfo *root,
 | 
					extern HashPath *create_hashjoin_path(PlannerInfo *root,
 | 
				
			||||||
									  RelOptInfo *joinrel,
 | 
														  RelOptInfo *joinrel,
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user