diff options
author | David Rowley <drowley@postgresql.org> | 2024-01-31 17:22:02 +1300 |
---|---|---|
committer | David Rowley <drowley@postgresql.org> | 2024-01-31 17:22:02 +1300 |
commit | b588cad688823b1e996ce05af4d88a954c005a3a (patch) | |
tree | 41ec222b7f8ad9ca83b80bd9be18e8815608fc60 /src/backend/optimizer/plan/planner.c | |
parent | 3e91dba8b079c02dc5204108c7e797b402c75779 (diff) | |
download | postgresql-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.c | 44 |
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)); + } } } |