22
22
* ExecEndIndexScan releases all storage.
23
23
* ExecIndexMarkPos marks scan position.
24
24
* ExecIndexRestrPos restores scan position.
25
+ * ExecIndexScanEstimate estimates DSM space needed for parallel index scan
26
+ * ExecIndexScanInitializeDSM initialize DSM for parallel indexscan
27
+ * ExecIndexScanInitializeWorker attach to DSM info in parallel worker
25
28
*/
26
29
#include "postgres.h"
27
30
@@ -514,6 +517,18 @@ ExecIndexScan(IndexScanState *node)
514
517
void
515
518
ExecReScanIndexScan (IndexScanState * node )
516
519
{
520
+ bool reset_parallel_scan = true;
521
+
522
+ /*
523
+ * If we are here to just update the scan keys, then don't reset parallel
524
+ * scan. We don't want each of the participating process in the parallel
525
+ * scan to update the shared parallel scan state at the start of the scan.
526
+ * It is quite possible that one of the participants has already begun
527
+ * scanning the index when another has yet to start it.
528
+ */
529
+ if (node -> iss_NumRuntimeKeys != 0 && !node -> iss_RuntimeKeysReady )
530
+ reset_parallel_scan = false;
531
+
517
532
/*
518
533
* If we are doing runtime key calculations (ie, any of the index key
519
534
* values weren't simple Consts), compute the new key values. But first,
@@ -539,10 +554,21 @@ ExecReScanIndexScan(IndexScanState *node)
539
554
reorderqueue_pop (node );
540
555
}
541
556
542
- /* reset index scan */
543
- index_rescan (node -> iss_ScanDesc ,
544
- node -> iss_ScanKeys , node -> iss_NumScanKeys ,
545
- node -> iss_OrderByKeys , node -> iss_NumOrderByKeys );
557
+ /*
558
+ * Reset (parallel) index scan. For parallel-aware nodes, the scan
559
+ * descriptor is initialized during actual execution of node and we can
560
+ * reach here before that (ex. during execution of nest loop join). So,
561
+ * avoid updating the scan descriptor at that time.
562
+ */
563
+ if (node -> iss_ScanDesc )
564
+ {
565
+ index_rescan (node -> iss_ScanDesc ,
566
+ node -> iss_ScanKeys , node -> iss_NumScanKeys ,
567
+ node -> iss_OrderByKeys , node -> iss_NumOrderByKeys );
568
+
569
+ if (reset_parallel_scan && node -> iss_ScanDesc -> parallel_scan )
570
+ index_parallelrescan (node -> iss_ScanDesc );
571
+ }
546
572
node -> iss_ReachedEnd = false;
547
573
548
574
ExecScanReScan (& node -> ss );
@@ -1013,22 +1039,29 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
1013
1039
}
1014
1040
1015
1041
/*
1016
- * Initialize scan descriptor.
1042
+ * for parallel-aware node, we initialize the scan descriptor after
1043
+ * initializing the shared memory for parallel execution.
1017
1044
*/
1018
- indexstate -> iss_ScanDesc = index_beginscan (currentRelation ,
1019
- indexstate -> iss_RelationDesc ,
1020
- estate -> es_snapshot ,
1021
- indexstate -> iss_NumScanKeys ,
1045
+ if (!node -> scan .plan .parallel_aware )
1046
+ {
1047
+ /*
1048
+ * Initialize scan descriptor.
1049
+ */
1050
+ indexstate -> iss_ScanDesc = index_beginscan (currentRelation ,
1051
+ indexstate -> iss_RelationDesc ,
1052
+ estate -> es_snapshot ,
1053
+ indexstate -> iss_NumScanKeys ,
1022
1054
indexstate -> iss_NumOrderByKeys );
1023
1055
1024
- /*
1025
- * If no run-time keys to calculate, go ahead and pass the scankeys to the
1026
- * index AM.
1027
- */
1028
- if (indexstate -> iss_NumRuntimeKeys == 0 )
1029
- index_rescan (indexstate -> iss_ScanDesc ,
1030
- indexstate -> iss_ScanKeys , indexstate -> iss_NumScanKeys ,
1056
+ /*
1057
+ * If no run-time keys to calculate, go ahead and pass the scankeys to
1058
+ * the index AM.
1059
+ */
1060
+ if (indexstate -> iss_NumRuntimeKeys == 0 )
1061
+ index_rescan (indexstate -> iss_ScanDesc ,
1062
+ indexstate -> iss_ScanKeys , indexstate -> iss_NumScanKeys ,
1031
1063
indexstate -> iss_OrderByKeys , indexstate -> iss_NumOrderByKeys );
1064
+ }
1032
1065
1033
1066
/*
1034
1067
* all done.
@@ -1590,3 +1623,91 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
1590
1623
else if (n_array_keys != 0 )
1591
1624
elog (ERROR , "ScalarArrayOpExpr index qual found where not allowed" );
1592
1625
}
1626
+
1627
+ /* ----------------------------------------------------------------
1628
+ * Parallel Scan Support
1629
+ * ----------------------------------------------------------------
1630
+ */
1631
+
1632
+ /* ----------------------------------------------------------------
1633
+ * ExecIndexScanEstimate
1634
+ *
1635
+ * estimates the space required to serialize indexscan node.
1636
+ * ----------------------------------------------------------------
1637
+ */
1638
+ void
1639
+ ExecIndexScanEstimate (IndexScanState * node ,
1640
+ ParallelContext * pcxt )
1641
+ {
1642
+ EState * estate = node -> ss .ps .state ;
1643
+
1644
+ node -> iss_PscanLen = index_parallelscan_estimate (node -> iss_RelationDesc ,
1645
+ estate -> es_snapshot );
1646
+ shm_toc_estimate_chunk (& pcxt -> estimator , node -> iss_PscanLen );
1647
+ shm_toc_estimate_keys (& pcxt -> estimator , 1 );
1648
+ }
1649
+
1650
+ /* ----------------------------------------------------------------
1651
+ * ExecIndexScanInitializeDSM
1652
+ *
1653
+ * Set up a parallel index scan descriptor.
1654
+ * ----------------------------------------------------------------
1655
+ */
1656
+ void
1657
+ ExecIndexScanInitializeDSM (IndexScanState * node ,
1658
+ ParallelContext * pcxt )
1659
+ {
1660
+ EState * estate = node -> ss .ps .state ;
1661
+ ParallelIndexScanDesc piscan ;
1662
+
1663
+ piscan = shm_toc_allocate (pcxt -> toc , node -> iss_PscanLen );
1664
+ index_parallelscan_initialize (node -> ss .ss_currentRelation ,
1665
+ node -> iss_RelationDesc ,
1666
+ estate -> es_snapshot ,
1667
+ piscan );
1668
+ shm_toc_insert (pcxt -> toc , node -> ss .ps .plan -> plan_node_id , piscan );
1669
+ node -> iss_ScanDesc =
1670
+ index_beginscan_parallel (node -> ss .ss_currentRelation ,
1671
+ node -> iss_RelationDesc ,
1672
+ node -> iss_NumScanKeys ,
1673
+ node -> iss_NumOrderByKeys ,
1674
+ piscan );
1675
+
1676
+ /*
1677
+ * If no run-time keys to calculate, go ahead and pass the scankeys to the
1678
+ * index AM.
1679
+ */
1680
+ if (node -> iss_NumRuntimeKeys == 0 )
1681
+ index_rescan (node -> iss_ScanDesc ,
1682
+ node -> iss_ScanKeys , node -> iss_NumScanKeys ,
1683
+ node -> iss_OrderByKeys , node -> iss_NumOrderByKeys );
1684
+ }
1685
+
1686
+ /* ----------------------------------------------------------------
1687
+ * ExecIndexScanInitializeWorker
1688
+ *
1689
+ * Copy relevant information from TOC into planstate.
1690
+ * ----------------------------------------------------------------
1691
+ */
1692
+ void
1693
+ ExecIndexScanInitializeWorker (IndexScanState * node , shm_toc * toc )
1694
+ {
1695
+ ParallelIndexScanDesc piscan ;
1696
+
1697
+ piscan = shm_toc_lookup (toc , node -> ss .ps .plan -> plan_node_id );
1698
+ node -> iss_ScanDesc =
1699
+ index_beginscan_parallel (node -> ss .ss_currentRelation ,
1700
+ node -> iss_RelationDesc ,
1701
+ node -> iss_NumScanKeys ,
1702
+ node -> iss_NumOrderByKeys ,
1703
+ piscan );
1704
+
1705
+ /*
1706
+ * If no run-time keys to calculate, go ahead and pass the scankeys to the
1707
+ * index AM.
1708
+ */
1709
+ if (node -> iss_NumRuntimeKeys == 0 )
1710
+ index_rescan (node -> iss_ScanDesc ,
1711
+ node -> iss_ScanKeys , node -> iss_NumScanKeys ,
1712
+ node -> iss_OrderByKeys , node -> iss_NumOrderByKeys );
1713
+ }
0 commit comments