Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit86b7cca

Browse files
committed
Check parallel safety in generate_useful_gather_paths
Commitebb7ae8 ensured we ignore pathkeys with volatile expressionswhen considering adding a sort below a Gather Merge. Turns out we needto care about parallel safety of the pathkeys too, otherwise we mighttry sorting e.g. on results of a correlated subquery (as demonstratedby a report from Luis Roberto).Initial investigation by Tom Lane, patch by James Coleman. Backpatchto 13, where the code was instroduced (as part of Incremental Sort).Reported-by: Luis RobertoAuthor: James ColemanReviewed-by: Tomas VondraBackpatch-through: 13Discussion:https://postgr.es/m/622580997.37108180.1604080457319.JavaMail.zimbra%40siscobra.com.brDiscussion:https://postgr.es/m/CAAaqYe8cK3g5CfLC4w7bs=hC0mSksZC=H5M8LSchj5e5OxpTAg@mail.gmail.com
1 parentf4a3c0b commit86b7cca

File tree

5 files changed

+73
-5
lines changed

5 files changed

+73
-5
lines changed

‎src/backend/optimizer/path/allpaths.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2802,14 +2802,18 @@ generate_gather_paths(PlannerInfo *root, RelOptInfo *rel, bool override_rows)
28022802
* This allows us to do incremental sort on top of an index scan under a gather
28032803
* merge node, i.e. parallelized.
28042804
*
2805+
* If the require_parallel_safe is true, we also require the expressions to
2806+
* be parallel safe (which allows pushing the sort below Gather Merge).
2807+
*
28052808
* XXX At the moment this can only ever return a list with a single element,
28062809
* because it looks at query_pathkeys only. So we might return the pathkeys
28072810
* directly, but it seems plausible we'll want to consider other orderings
28082811
* in the future. For example, we might want to consider pathkeys useful for
28092812
* merge joins.
28102813
*/
28112814
staticList*
2812-
get_useful_pathkeys_for_relation(PlannerInfo*root,RelOptInfo*rel)
2815+
get_useful_pathkeys_for_relation(PlannerInfo*root,RelOptInfo*rel,
2816+
boolrequire_parallel_safe)
28132817
{
28142818
List*useful_pathkeys_list=NIL;
28152819

@@ -2839,8 +2843,11 @@ get_useful_pathkeys_for_relation(PlannerInfo *root, RelOptInfo *rel)
28392843
* meet criteria of EC membership in the current relation, we
28402844
* enable not just an incremental sort on the entirety of
28412845
* query_pathkeys but also incremental sort below a JOIN.
2846+
*
2847+
* If requested, ensure the expression is parallel safe too.
28422848
*/
2843-
if (!find_em_expr_usable_for_sorting_rel(pathkey_ec,rel))
2849+
if (!find_em_expr_usable_for_sorting_rel(root,pathkey_ec,rel,
2850+
require_parallel_safe))
28442851
break;
28452852

28462853
npathkeys++;
@@ -2894,7 +2901,7 @@ generate_useful_gather_paths(PlannerInfo *root, RelOptInfo *rel, bool override_r
28942901
generate_gather_paths(root,rel,override_rows);
28952902

28962903
/* consider incremental sort for interesting orderings */
2897-
useful_pathkeys_list=get_useful_pathkeys_for_relation(root,rel);
2904+
useful_pathkeys_list=get_useful_pathkeys_for_relation(root,rel, true);
28982905

28992906
/* used for explicit (full) sort paths */
29002907
cheapest_partial_path=linitial(rel->partial_pathlist);

‎src/backend/optimizer/path/equivclass.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -803,7 +803,8 @@ find_em_expr_for_rel(EquivalenceClass *ec, RelOptInfo *rel)
803803
* applied in prepare_sort_from_pathkeys.
804804
*/
805805
Expr*
806-
find_em_expr_usable_for_sorting_rel(EquivalenceClass*ec,RelOptInfo*rel)
806+
find_em_expr_usable_for_sorting_rel(PlannerInfo*root,EquivalenceClass*ec,
807+
RelOptInfo*rel,boolrequire_parallel_safe)
807808
{
808809
ListCell*lc_em;
809810

@@ -833,6 +834,12 @@ find_em_expr_usable_for_sorting_rel(EquivalenceClass *ec, RelOptInfo *rel)
833834
if (!bms_is_subset(em->em_relids,rel->relids))
834835
continue;
835836

837+
/*
838+
* If requested, reject expressions that are not parallel-safe.
839+
*/
840+
if (require_parallel_safe&& !is_parallel_safe(root, (Node*)em_expr))
841+
continue;
842+
836843
/*
837844
* As long as the expression isn't volatile then
838845
* prepare_sort_from_pathkeys is able to generate a new target entry,

‎src/include/optimizer/paths.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,10 @@ extern EquivalenceClass *get_eclass_for_sort_expr(PlannerInfo *root,
135135
Relidsrel,
136136
boolcreate_it);
137137
externExpr*find_em_expr_for_rel(EquivalenceClass*ec,RelOptInfo*rel);
138-
externExpr*find_em_expr_usable_for_sorting_rel(EquivalenceClass*ec,RelOptInfo*rel);
138+
externExpr*find_em_expr_usable_for_sorting_rel(PlannerInfo*root,
139+
EquivalenceClass*ec,
140+
RelOptInfo*rel,
141+
boolrequire_parallel_safe);
139142
externvoidgenerate_base_implied_equalities(PlannerInfo*root);
140143
externList*generate_join_implied_equalities(PlannerInfo*root,
141144
Relidsjoin_relids,

‎src/test/regress/expected/incremental_sort.out

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1551,6 +1551,46 @@ order by 1, 2;
15511551
-> Function Scan on generate_series
15521552
(7 rows)
15531553

1554+
-- Parallel sort but with expression (correlated subquery) that
1555+
-- is prohibited in parallel plans.
1556+
explain (costs off) select distinct
1557+
unique1,
1558+
(select t.unique1 from tenk1 where tenk1.unique1 = t.unique1)
1559+
from tenk1 t, generate_series(1, 1000);
1560+
QUERY PLAN
1561+
---------------------------------------------------------------------------------
1562+
Unique
1563+
-> Sort
1564+
Sort Key: t.unique1, ((SubPlan 1))
1565+
-> Gather
1566+
Workers Planned: 2
1567+
-> Nested Loop
1568+
-> Parallel Index Only Scan using tenk1_unique1 on tenk1 t
1569+
-> Function Scan on generate_series
1570+
SubPlan 1
1571+
-> Index Only Scan using tenk1_unique1 on tenk1
1572+
Index Cond: (unique1 = t.unique1)
1573+
(11 rows)
1574+
1575+
explain (costs off) select
1576+
unique1,
1577+
(select t.unique1 from tenk1 where tenk1.unique1 = t.unique1)
1578+
from tenk1 t, generate_series(1, 1000)
1579+
order by 1, 2;
1580+
QUERY PLAN
1581+
---------------------------------------------------------------------------
1582+
Sort
1583+
Sort Key: t.unique1, ((SubPlan 1))
1584+
-> Gather
1585+
Workers Planned: 2
1586+
-> Nested Loop
1587+
-> Parallel Index Only Scan using tenk1_unique1 on tenk1 t
1588+
-> Function Scan on generate_series
1589+
SubPlan 1
1590+
-> Index Only Scan using tenk1_unique1 on tenk1
1591+
Index Cond: (unique1 = t.unique1)
1592+
(10 rows)
1593+
15541594
-- Parallel sort but with expression not available until the upper rel.
15551595
explain (costs off) select distinct sub.unique1, stringu1 || random()::text
15561596
from tenk1, lateral (select tenk1.unique1 from generate_series(1, 1000)) as sub;

‎src/test/regress/sql/incremental_sort.sql

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,17 @@ from tenk1, lateral (select tenk1.unique1 from generate_series(1, 1000)) as sub;
250250
explain (costs off)selectsub.unique1, md5(stringu1)
251251
from tenk1, lateral (selecttenk1.unique1from generate_series(1,1000))as sub
252252
order by1,2;
253+
-- Parallel sort but with expression (correlated subquery) that
254+
-- is prohibited in parallel plans.
255+
explain (costs off)select distinct
256+
unique1,
257+
(selectt.unique1from tenk1wheretenk1.unique1=t.unique1)
258+
from tenk1 t, generate_series(1,1000);
259+
explain (costs off)select
260+
unique1,
261+
(selectt.unique1from tenk1wheretenk1.unique1=t.unique1)
262+
from tenk1 t, generate_series(1,1000)
263+
order by1,2;
253264
-- Parallel sort but with expression not available until the upper rel.
254265
explain (costs off)select distinctsub.unique1, stringu1|| random()::text
255266
from tenk1, lateral (selecttenk1.unique1from generate_series(1,1000))as sub;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp