]> granicus.if.org Git - postgresql/commitdiff
Fix parallel index and index-only scans to fall back to serial.
authorRobert Haas <rhaas@postgresql.org>
Wed, 8 Mar 2017 13:15:24 +0000 (08:15 -0500)
committerRobert Haas <rhaas@postgresql.org>
Wed, 8 Mar 2017 13:15:24 +0000 (08:15 -0500)
Parallel executor nodes can't assume that parallel execution will
happen in every case where the plan calls for it, because it might
not work out that way.  However, parallel index scan and parallel
index-only scan failed to do the right thing here.  Repair.

Amit Kapila, per a report from me.

Discussion: http://postgr.es/m/CAA4eK1Kq5qb_u2AOoda5XBB91vVWz90w=LgtRLgsssriS8pVTw@mail.gmail.com

src/backend/executor/nodeIndexonlyscan.c
src/backend/executor/nodeIndexscan.c

index 4a7f39a7c7d096b1fe3547f7ef306cbdc5841396..db7f2e120ea85b99dd2d22e784d5d449b1d0101f 100644 (file)
@@ -78,6 +78,38 @@ IndexOnlyNext(IndexOnlyScanState *node)
        econtext = node->ss.ps.ps_ExprContext;
        slot = node->ss.ss_ScanTupleSlot;
 
+       if (scandesc == NULL)
+       {
+               /*
+                * We reach here if the index only scan is not parallel, or if we're
+                * executing a index only scan that was intended to be parallel
+                * serially.
+                */
+               scandesc = index_beginscan(node->ss.ss_currentRelation,
+                                                                  node->ioss_RelationDesc,
+                                                                  estate->es_snapshot,
+                                                                  node->ioss_NumScanKeys,
+                                                                  node->ioss_NumOrderByKeys);
+
+               node->ioss_ScanDesc = scandesc;
+
+
+               /* Set it up for index-only scan */
+               node->ioss_ScanDesc->xs_want_itup = true;
+               node->ioss_VMBuffer = InvalidBuffer;
+
+               /*
+                * If no run-time keys to calculate or they are ready, go ahead and
+                * pass the scankeys to the index AM.
+                */
+               if (node->ioss_NumRuntimeKeys == 0 || node->ioss_RuntimeKeysReady)
+                       index_rescan(scandesc,
+                                                node->ioss_ScanKeys,
+                                                node->ioss_NumScanKeys,
+                                                node->ioss_OrderByKeys,
+                                                node->ioss_NumOrderByKeys);
+       }
+
        /*
         * OK, now that we have what we need, fetch the next tuple.
         */
@@ -571,34 +603,6 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags)
                indexstate->ioss_RuntimeContext = NULL;
        }
 
-       /*
-        * Initialize scan descriptor.
-        */
-       if (!node->scan.plan.parallel_aware)
-       {
-               indexstate->ioss_ScanDesc = index_beginscan(currentRelation,
-                                                                                          indexstate->ioss_RelationDesc,
-                                                                                                       estate->es_snapshot,
-                                                                                               indexstate->ioss_NumScanKeys,
-                                                                                       indexstate->ioss_NumOrderByKeys);
-
-
-               /* Set it up for index-only scan */
-               indexstate->ioss_ScanDesc->xs_want_itup = true;
-               indexstate->ioss_VMBuffer = InvalidBuffer;
-
-               /*
-                * If no run-time keys to calculate, go ahead and pass the scankeys to
-                * the index AM.
-                */
-               if (indexstate->ioss_NumRuntimeKeys == 0)
-                       index_rescan(indexstate->ioss_ScanDesc,
-                                                indexstate->ioss_ScanKeys,
-                                                indexstate->ioss_NumScanKeys,
-                                                indexstate->ioss_OrderByKeys,
-                                                indexstate->ioss_NumOrderByKeys);
-       }
-
        /*
         * all done.
         */
@@ -657,10 +661,10 @@ ExecIndexOnlyScanInitializeDSM(IndexOnlyScanState *node,
        node->ioss_VMBuffer = InvalidBuffer;
 
        /*
-        * If no run-time keys to calculate, go ahead and pass the scankeys to
-        * the index AM.
+        * If no run-time keys to calculate or they are ready, go ahead and pass
+        * the scankeys to the index AM.
         */
-       if (node->ioss_NumRuntimeKeys == 0)
+       if (node->ioss_NumRuntimeKeys == 0 || node->ioss_RuntimeKeysReady)
                index_rescan(node->ioss_ScanDesc,
                                         node->ioss_ScanKeys, node->ioss_NumScanKeys,
                                         node->ioss_OrderByKeys, node->ioss_NumOrderByKeys);
@@ -687,10 +691,10 @@ ExecIndexOnlyScanInitializeWorker(IndexOnlyScanState *node, shm_toc *toc)
        node->ioss_ScanDesc->xs_want_itup = true;
 
        /*
-        * If no run-time keys to calculate, go ahead and pass the scankeys to the
-        * index AM.
+        * If no run-time keys to calculate or they are ready, go ahead and pass
+        * the scankeys to the index AM.
         */
-       if (node->ioss_NumRuntimeKeys == 0)
+       if (node->ioss_NumRuntimeKeys == 0 || node->ioss_RuntimeKeysReady)
                index_rescan(node->ioss_ScanDesc,
                                         node->ioss_ScanKeys, node->ioss_NumScanKeys,
                                         node->ioss_OrderByKeys, node->ioss_NumOrderByKeys);
index 0a9dfdbaf3054c1ea2b5680fa2d8d2fba2d4a315..cb6aff9137a42908c46e98d0323b80e9d06bf2d1 100644 (file)
@@ -102,6 +102,30 @@ IndexNext(IndexScanState *node)
        econtext = node->ss.ps.ps_ExprContext;
        slot = node->ss.ss_ScanTupleSlot;
 
+       if (scandesc == NULL)
+       {
+               /*
+                * We reach here if the index scan is not parallel, or if we're
+                * executing a index scan that was intended to be parallel serially.
+                */
+               scandesc = index_beginscan(node->ss.ss_currentRelation,
+                                                                  node->iss_RelationDesc,
+                                                                  estate->es_snapshot,
+                                                                  node->iss_NumScanKeys,
+                                                                  node->iss_NumOrderByKeys);
+
+               node->iss_ScanDesc = scandesc;
+
+               /*
+                * If no run-time keys to calculate or they are ready, go ahead and
+                * pass the scankeys to the index AM.
+                */
+               if (node->iss_NumRuntimeKeys == 0 || node->iss_RuntimeKeysReady)
+                       index_rescan(scandesc,
+                                                node->iss_ScanKeys, node->iss_NumScanKeys,
+                                                node->iss_OrderByKeys, node->iss_NumOrderByKeys);
+       }
+
        /*
         * ok, now that we have what we need, fetch the next tuple.
         */
@@ -154,6 +178,7 @@ IndexNext(IndexScanState *node)
 static TupleTableSlot *
 IndexNextWithReorder(IndexScanState *node)
 {
+       EState     *estate;
        ExprContext *econtext;
        IndexScanDesc scandesc;
        HeapTuple       tuple;
@@ -164,6 +189,8 @@ IndexNextWithReorder(IndexScanState *node)
        bool       *lastfetched_nulls;
        int                     cmp;
 
+       estate = node->ss.ps.state;
+
        /*
         * Only forward scan is supported with reordering.  Note: we can get away
         * with just Asserting here because the system will not try to run the
@@ -174,12 +201,36 @@ IndexNextWithReorder(IndexScanState *node)
         * explicitly.
         */
        Assert(!ScanDirectionIsBackward(((IndexScan *) node->ss.ps.plan)->indexorderdir));
-       Assert(ScanDirectionIsForward(node->ss.ps.state->es_direction));
+       Assert(ScanDirectionIsForward(estate->es_direction));
 
        scandesc = node->iss_ScanDesc;
        econtext = node->ss.ps.ps_ExprContext;
        slot = node->ss.ss_ScanTupleSlot;
 
+       if (scandesc == NULL)
+       {
+               /*
+                * We reach here if the index scan is not parallel, or if we're
+                * executing a index scan that was intended to be parallel serially.
+                */
+               scandesc = index_beginscan(node->ss.ss_currentRelation,
+                                                                  node->iss_RelationDesc,
+                                                                  estate->es_snapshot,
+                                                                  node->iss_NumScanKeys,
+                                                                  node->iss_NumOrderByKeys);
+
+               node->iss_ScanDesc = scandesc;
+
+               /*
+                * If no run-time keys to calculate or they are ready, go ahead and
+                * pass the scankeys to the index AM.
+                */
+               if (node->iss_NumRuntimeKeys == 0 || node->iss_RuntimeKeysReady)
+                       index_rescan(scandesc,
+                                                node->iss_ScanKeys, node->iss_NumScanKeys,
+                                                node->iss_OrderByKeys, node->iss_NumOrderByKeys);
+       }
+
        for (;;)
        {
                /*
@@ -1038,31 +1089,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
                indexstate->iss_RuntimeContext = NULL;
        }
 
-       /*
-        * for parallel-aware node, we initialize the scan descriptor after
-        * initializing the shared memory for parallel execution.
-        */
-       if (!node->scan.plan.parallel_aware)
-       {
-               /*
-                * Initialize scan descriptor.
-                */
-               indexstate->iss_ScanDesc = index_beginscan(currentRelation,
-                                                                                               indexstate->iss_RelationDesc,
-                                                                                                  estate->es_snapshot,
-                                                                                                indexstate->iss_NumScanKeys,
-                                                                                        indexstate->iss_NumOrderByKeys);
-
-               /*
-                * If no run-time keys to calculate, go ahead and pass the scankeys to
-                * the index AM.
-                */
-               if (indexstate->iss_NumRuntimeKeys == 0)
-                       index_rescan(indexstate->iss_ScanDesc,
-                                          indexstate->iss_ScanKeys, indexstate->iss_NumScanKeys,
-                               indexstate->iss_OrderByKeys, indexstate->iss_NumOrderByKeys);
-       }
-
        /*
         * all done.
         */
@@ -1674,10 +1700,10 @@ ExecIndexScanInitializeDSM(IndexScanState *node,
                                                                 piscan);
 
        /*
-        * If no run-time keys to calculate, go ahead and pass the scankeys to the
-        * index AM.
+        * If no run-time keys to calculate or they are ready, go ahead and pass
+        * the scankeys to the index AM.
         */
-       if (node->iss_NumRuntimeKeys == 0)
+       if (node->iss_NumRuntimeKeys == 0 || node->iss_RuntimeKeysReady)
                index_rescan(node->iss_ScanDesc,
                                         node->iss_ScanKeys, node->iss_NumScanKeys,
                                         node->iss_OrderByKeys, node->iss_NumOrderByKeys);
@@ -1703,10 +1729,10 @@ ExecIndexScanInitializeWorker(IndexScanState *node, shm_toc *toc)
                                                                 piscan);
 
        /*
-        * If no run-time keys to calculate, go ahead and pass the scankeys to the
-        * index AM.
+        * If no run-time keys to calculate or they are ready, go ahead and pass
+        * the scankeys to the index AM.
         */
-       if (node->iss_NumRuntimeKeys == 0)
+       if (node->iss_NumRuntimeKeys == 0 || node->iss_RuntimeKeysReady)
                index_rescan(node->iss_ScanDesc,
                                         node->iss_ScanKeys, node->iss_NumScanKeys,
                                         node->iss_OrderByKeys, node->iss_NumOrderByKeys);