21
21
#include "access/tsmapi.h"
22
22
#include "catalog/pg_class.h"
23
23
#include "catalog/pg_operator.h"
24
+ #include "catalog/pg_proc.h"
24
25
#include "foreign/fdwapi.h"
25
26
#include "nodes/makefuncs.h"
26
27
#include "nodes/nodeFuncs.h"
@@ -71,6 +72,9 @@ static void set_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
71
72
Index rti , RangeTblEntry * rte );
72
73
static void set_plain_rel_size (PlannerInfo * root , RelOptInfo * rel ,
73
74
RangeTblEntry * rte );
75
+ static void set_rel_consider_parallel (PlannerInfo * root , RelOptInfo * rel ,
76
+ RangeTblEntry * rte );
77
+ static bool function_rte_parallel_ok (RangeTblEntry * rte );
74
78
static void set_plain_rel_pathlist (PlannerInfo * root , RelOptInfo * rel ,
75
79
RangeTblEntry * rte );
76
80
static void set_tablesample_rel_size (PlannerInfo * root , RelOptInfo * rel ,
@@ -158,7 +162,8 @@ make_one_rel(PlannerInfo *root, List *joinlist)
158
162
set_base_rel_consider_startup (root );
159
163
160
164
/*
161
- * Generate access paths for the base rels.
165
+ * Generate access paths for the base rels. set_base_rel_sizes also
166
+ * sets the consider_parallel flag for each baserel, if appropriate.
162
167
*/
163
168
set_base_rel_sizes (root );
164
169
set_base_rel_pathlists (root );
@@ -222,9 +227,12 @@ set_base_rel_consider_startup(PlannerInfo *root)
222
227
/*
223
228
* set_base_rel_sizes
224
229
* Set the size estimates (rows and widths) for each base-relation entry.
230
+ * Also determine whether to consider parallel paths for base relations.
225
231
*
226
232
* We do this in a separate pass over the base rels so that rowcount
227
- * estimates are available for parameterized path generation.
233
+ * estimates are available for parameterized path generation, and also so
234
+ * that the consider_parallel flag is set correctly before we begin to
235
+ * generate paths.
228
236
*/
229
237
static void
230
238
set_base_rel_sizes (PlannerInfo * root )
@@ -234,6 +242,7 @@ set_base_rel_sizes(PlannerInfo *root)
234
242
for (rti = 1 ; rti < root -> simple_rel_array_size ; rti ++ )
235
243
{
236
244
RelOptInfo * rel = root -> simple_rel_array [rti ];
245
+ RangeTblEntry * rte ;
237
246
238
247
/* there may be empty slots corresponding to non-baserel RTEs */
239
248
if (rel == NULL )
@@ -245,7 +254,19 @@ set_base_rel_sizes(PlannerInfo *root)
245
254
if (rel -> reloptkind != RELOPT_BASEREL )
246
255
continue ;
247
256
248
- set_rel_size (root , rel , rti , root -> simple_rte_array [rti ]);
257
+ rte = root -> simple_rte_array [rti ];
258
+
259
+ /*
260
+ * If parallelism is allowable for this query in general, see whether
261
+ * it's allowable for this rel in particular. We have to do this
262
+ * before set_rel_size, because that if this is an inheritance parent,
263
+ * set_append_rel_size will pass the consider_parallel flag down to
264
+ * inheritance children.
265
+ */
266
+ if (root -> glob -> parallelModeOK )
267
+ set_rel_consider_parallel (root , rel , rte );
268
+
269
+ set_rel_size (root , rel , rti , rte );
249
270
}
250
271
}
251
272
@@ -458,6 +479,131 @@ set_plain_rel_size(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
458
479
set_baserel_size_estimates (root , rel );
459
480
}
460
481
482
+ /*
483
+ * If this relation could possibly be scanned from within a worker, then set
484
+ * the consider_parallel flag. The flag has previously been initialized to
485
+ * false, so we just bail out if it becomes clear that we can't safely set it.
486
+ */
487
+ static void
488
+ set_rel_consider_parallel (PlannerInfo * root , RelOptInfo * rel ,
489
+ RangeTblEntry * rte )
490
+ {
491
+ /* Don't call this if parallelism is disallowed for the entire query. */
492
+ Assert (root -> glob -> parallelModeOK );
493
+
494
+ /* Don't call this for non-baserels. */
495
+ Assert (rel -> reloptkind == RELOPT_BASEREL );
496
+
497
+ /* Assorted checks based on rtekind. */
498
+ switch (rte -> rtekind )
499
+ {
500
+ case RTE_RELATION :
501
+ /*
502
+ * Currently, parallel workers can't access the leader's temporary
503
+ * tables. We could possibly relax this if the wrote all of its
504
+ * local buffers at the start of the query and made no changes
505
+ * thereafter (maybe we could allow hint bit changes), and if we
506
+ * taught the workers to read them. Writing a large number of
507
+ * temporary buffers could be expensive, though, and we don't have
508
+ * the rest of the necessary infrastructure right now anyway. So
509
+ * for now, bail out if we see a temporary table.
510
+ */
511
+ if (get_rel_persistence (rte -> relid ) == RELPERSISTENCE_TEMP )
512
+ return ;
513
+
514
+ /*
515
+ * Table sampling can be pushed down to workers if the sample
516
+ * function and its arguments are safe.
517
+ */
518
+ if (rte -> tablesample != NULL )
519
+ {
520
+ Oid proparallel = func_parallel (rte -> tablesample -> tsmhandler );
521
+
522
+ if (proparallel != PROPARALLEL_SAFE )
523
+ return ;
524
+ if (has_parallel_hazard ((Node * ) rte -> tablesample -> args ,
525
+ false))
526
+ return ;
527
+ return ;
528
+ }
529
+ break ;
530
+
531
+ case RTE_SUBQUERY :
532
+ /*
533
+ * Subplans currently aren't passed to workers. Even if they
534
+ * were, the subplan might be using parallelism internally, and
535
+ * we can't support nested Gather nodes at present. Finally,
536
+ * we don't have a good way of knowing whether the subplan
537
+ * involves any parallel-restricted operations. It would be
538
+ * nice to relax this restriction some day, but it's going to
539
+ * take a fair amount of work.
540
+ */
541
+ return ;
542
+
543
+ case RTE_JOIN :
544
+ /* Shouldn't happen; we're only considering baserels here. */
545
+ Assert (false);
546
+ return ;
547
+
548
+ case RTE_FUNCTION :
549
+ /* Check for parallel-restricted functions. */
550
+ if (!function_rte_parallel_ok (rte ))
551
+ return ;
552
+ break ;
553
+
554
+ case RTE_VALUES :
555
+ /*
556
+ * The data for a VALUES clause is stored in the plan tree itself,
557
+ * so scanning it in a worker is fine.
558
+ */
559
+ break ;
560
+
561
+ case RTE_CTE :
562
+ /*
563
+ * CTE tuplestores aren't shared among parallel workers, so we
564
+ * force all CTE scans to happen in the leader. Also, populating
565
+ * the CTE would require executing a subplan that's not available
566
+ * in the worker, might be parallel-restricted, and must get
567
+ * executed only once.
568
+ */
569
+ return ;
570
+ }
571
+
572
+ /*
573
+ * If there's anything in baserestrictinfo that's parallel-restricted,
574
+ * we give up on parallelizing access to this relation. We could consider
575
+ * instead postponing application of the restricted quals until we're
576
+ * above all the parallelism in the plan tree, but it's not clear that
577
+ * this would be a win in very many cases, and it might be tricky to make
578
+ * outer join clauses work correctly.
579
+ */
580
+ if (has_parallel_hazard ((Node * ) rel -> baserestrictinfo , false))
581
+ return ;
582
+
583
+ /* We have a winner. */
584
+ rel -> consider_parallel = true;
585
+ }
586
+
587
+ /*
588
+ * Check whether a function RTE is scanning something parallel-restricted.
589
+ */
590
+ static bool
591
+ function_rte_parallel_ok (RangeTblEntry * rte )
592
+ {
593
+ ListCell * lc ;
594
+
595
+ foreach (lc , rte -> functions )
596
+ {
597
+ RangeTblFunction * rtfunc = (RangeTblFunction * ) lfirst (lc );
598
+
599
+ Assert (IsA (rtfunc , RangeTblFunction ));
600
+ if (has_parallel_hazard (rtfunc -> funcexpr , false))
601
+ return false;
602
+ }
603
+
604
+ return true;
605
+ }
606
+
461
607
/*
462
608
* set_plain_rel_pathlist
463
609
* Build access paths for a plain relation (no subquery, no inheritance)
@@ -466,6 +612,7 @@ static void
466
612
set_plain_rel_pathlist (PlannerInfo * root , RelOptInfo * rel , RangeTblEntry * rte )
467
613
{
468
614
Relids required_outer ;
615
+ int parallel_threshold = 1000 ;
469
616
470
617
/*
471
618
* We don't support pushing join clauses into the quals of a seqscan, but
@@ -477,6 +624,40 @@ set_plain_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
477
624
/* Consider sequential scan */
478
625
add_path (rel , create_seqscan_path (root , rel , required_outer , 0 ));
479
626
627
+ /* Consider parallel sequential scan */
628
+ if (rel -> consider_parallel && rel -> pages > parallel_threshold &&
629
+ required_outer == NULL )
630
+ {
631
+ Path * path ;
632
+ int parallel_degree = 1 ;
633
+
634
+ /*
635
+ * Limit the degree of parallelism logarithmically based on the size
636
+ * of the relation. This probably needs to be a good deal more
637
+ * sophisticated, but we need something here for now.
638
+ */
639
+ while (rel -> pages > parallel_threshold * 3 &&
640
+ parallel_degree < max_parallel_degree )
641
+ {
642
+ parallel_degree ++ ;
643
+ parallel_threshold *= 3 ;
644
+ if (parallel_threshold >= PG_INT32_MAX / 3 )
645
+ break ;
646
+ }
647
+
648
+ /*
649
+ * Ideally we should consider postponing the gather operation until
650
+ * much later, after we've pushed joins and so on atop the parallel
651
+ * sequential scan path. But we don't have the infrastructure for
652
+ * that yet, so just do this for now.
653
+ */
654
+ path = create_seqscan_path (root , rel , required_outer , parallel_degree );
655
+ path = (Path * )
656
+ create_gather_path (root , rel , path , required_outer ,
657
+ parallel_degree );
658
+ add_path (rel , path );
659
+ }
660
+
480
661
/* Consider index scans */
481
662
create_index_paths (root , rel );
482
663
@@ -714,6 +895,9 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
714
895
continue ;
715
896
}
716
897
898
+ /* Copy consider_parallel flag from parent. */
899
+ childrel -> consider_parallel = rel -> consider_parallel ;
900
+
717
901
/*
718
902
* CE failed, so finish copying/modifying targetlist and join quals.
719
903
*
0 commit comments