aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan/planner.c
diff options
context:
space:
mode:
authorDavid Rowley <drowley@postgresql.org>2024-01-31 17:22:02 +1300
committerDavid Rowley <drowley@postgresql.org>2024-01-31 17:22:02 +1300
commitb588cad688823b1e996ce05af4d88a954c005a3a (patch)
tree41ec222b7f8ad9ca83b80bd9be18e8815608fc60 /src/backend/optimizer/plan/planner.c
parent3e91dba8b079c02dc5204108c7e797b402c75779 (diff)
downloadpostgresql-b588cad688823b1e996ce05af4d88a954c005a3a.tar.gz
postgresql-b588cad688823b1e996ce05af4d88a954c005a3a.zip
Consider the "LIMIT 1" optimization with parallel DISTINCT
Similar to what was done in 5543677ec for non-parallel DISTINCT, apply the same optimization when the distinct_pathkeys are empty for the partial paths too. This can be faster than the non-parallel version when the first row matching the WHERE clause of the query takes a while to find. Parallel workers could speed that process up considerably. Author: Richard Guo Reviewed-by: David Rowley Discussion: https://postgr.es/m/CAMbWs49JC0qvfUbzs-TVzgMpSSBiMJ_6sN=BaA9iohBgYkr=LA@mail.gmail.com
Diffstat (limited to 'src/backend/optimizer/plan/planner.c')
-rw-r--r--src/backend/optimizer/plan/planner.c44
1 files changed, 39 insertions, 5 deletions
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 01fa45b9255..342f5ad8d0a 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -4737,11 +4737,45 @@ create_partial_distinct_paths(PlannerInfo *root, RelOptInfo *input_rel,
-1.0);
}
- add_partial_path(partial_distinct_rel, (Path *)
- create_upper_unique_path(root, partial_distinct_rel,
- sorted_path,
- list_length(root->distinct_pathkeys),
- numDistinctRows));
+ /*
+ * An empty distinct_pathkeys means all tuples have the same value
+ * for the DISTINCT clause. See create_final_distinct_paths()
+ */
+ if (root->distinct_pathkeys == NIL)
+ {
+ Node *limitCount;
+
+ limitCount = (Node *) makeConst(INT8OID, -1, InvalidOid,
+ sizeof(int64),
+ Int64GetDatum(1), false,
+ FLOAT8PASSBYVAL);
+
+ /*
+ * Apply a LimitPath onto the partial path to restrict the
+ * tuples from each worker to 1. create_final_distinct_paths
+ * will need to apply an additional LimitPath to restrict this
+ * to a single row after the Gather node. If the query
+ * already has a LIMIT clause, then we could end up with three
+ * Limit nodes in the final plan. Consolidating the top two
+ * of these could be done, but does not seem worth troubling
+ * over.
+ */
+ add_partial_path(partial_distinct_rel, (Path *)
+ create_limit_path(root, partial_distinct_rel,
+ sorted_path,
+ NULL,
+ limitCount,
+ LIMIT_OPTION_COUNT,
+ 0, 1));
+ }
+ else
+ {
+ add_partial_path(partial_distinct_rel, (Path *)
+ create_upper_unique_path(root, partial_distinct_rel,
+ sorted_path,
+ list_length(root->distinct_pathkeys),
+ numDistinctRows));
+ }
}
}