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

Commitbe9c3cd

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 parentea190ed commitbe9c3cd

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
@@ -2742,14 +2742,18 @@ generate_gather_paths(PlannerInfo *root, RelOptInfo *rel, bool override_rows)
27422742
* This allows us to do incremental sort on top of an index scan under a gather
27432743
* merge node, i.e. parallelized.
27442744
*
2745+
* If the require_parallel_safe is true, we also require the expressions to
2746+
* be parallel safe (which allows pushing the sort below Gather Merge).
2747+
*
27452748
* XXX At the moment this can only ever return a list with a single element,
27462749
* because it looks at query_pathkeys only. So we might return the pathkeys
27472750
* directly, but it seems plausible we'll want to consider other orderings
27482751
* in the future. For example, we might want to consider pathkeys useful for
27492752
* merge joins.
27502753
*/
27512754
staticList*
2752-
get_useful_pathkeys_for_relation(PlannerInfo*root,RelOptInfo*rel)
2755+
get_useful_pathkeys_for_relation(PlannerInfo*root,RelOptInfo*rel,
2756+
boolrequire_parallel_safe)
27532757
{
27542758
List*useful_pathkeys_list=NIL;
27552759

@@ -2779,8 +2783,11 @@ get_useful_pathkeys_for_relation(PlannerInfo *root, RelOptInfo *rel)
27792783
* meet criteria of EC membership in the current relation, we
27802784
* enable not just an incremental sort on the entirety of
27812785
* query_pathkeys but also incremental sort below a JOIN.
2786+
*
2787+
* If requested, ensure the expression is parallel safe too.
27822788
*/
2783-
if (!find_em_expr_usable_for_sorting_rel(pathkey_ec,rel))
2789+
if (!find_em_expr_usable_for_sorting_rel(root,pathkey_ec,rel,
2790+
require_parallel_safe))
27842791
break;
27852792

27862793
npathkeys++;
@@ -2834,7 +2841,7 @@ generate_useful_gather_paths(PlannerInfo *root, RelOptInfo *rel, bool override_r
28342841
generate_gather_paths(root,rel,override_rows);
28352842

28362843
/* consider incremental sort for interesting orderings */
2837-
useful_pathkeys_list=get_useful_pathkeys_for_relation(root,rel);
2844+
useful_pathkeys_list=get_useful_pathkeys_for_relation(root,rel, true);
28382845

28392846
/* used for explicit (full) sort paths */
28402847
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
@@ -800,7 +800,8 @@ find_em_expr_for_rel(EquivalenceClass *ec, RelOptInfo *rel)
800800
* applied in prepare_sort_from_pathkeys.
801801
*/
802802
Expr*
803-
find_em_expr_usable_for_sorting_rel(EquivalenceClass*ec,RelOptInfo*rel)
803+
find_em_expr_usable_for_sorting_rel(PlannerInfo*root,EquivalenceClass*ec,
804+
RelOptInfo*rel,boolrequire_parallel_safe)
804805
{
805806
ListCell*lc_em;
806807

@@ -830,6 +831,12 @@ find_em_expr_usable_for_sorting_rel(EquivalenceClass *ec, RelOptInfo *rel)
830831
if (!bms_is_subset(em->em_relids,rel->relids))
831832
continue;
832833

834+
/*
835+
* If requested, reject expressions that are not parallel-safe.
836+
*/
837+
if (require_parallel_safe&& !is_parallel_safe(root, (Node*)em_expr))
838+
continue;
839+
833840
/*
834841
* As long as the expression isn't volatile then
835842
* 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