int         itemIndex;
    bool        continuescan;
    int         indnatts;
-   bool        requiredMatchedByPrecheck;
+   bool        continuescanPrechecked;
+   bool        haveFirstMatch = false;
 
    /*
     * We must have the buffer pinned and locked, but the usual macro can't be
    Assert(BTScanPosIsPinned(so->currPos));
 
    /*
-    * Prechecking the page with scan keys required for direction scan.  We
-    * check these keys with the last item on the page (according to our scan
-    * direction).  If these keys are matched, we can skip checking them with
-    * every item on the page.  Scan keys for our scan direction would
-    * necessarily match the previous items.  Scan keys required for opposite
-    * direction scan are already matched by the _bt_first() call.
+    * Prechecking the value of the continuescan flag for the last item on the
+    * page (for backwards scan it will be the first item on a page).  If we
+    * observe it to be true, then it should be true for all other items. This
+    * allows us to do significant optimizations in the _bt_checkkeys()
+    * function for all the items on the page.
     *
     * With the forward scan, we do this check for the last item on the page
     * instead of the high key.  It's relatively likely that the most
        itup = (IndexTuple) PageGetItem(page, iid);
 
        /*
-        * Do the precheck.  Note that we pass the pointer to
-        * 'requiredMatchedByPrecheck' to 'continuescan' argument.  That will
+        * Do the precheck.  Note that we pass the pointer to the
+        * 'continuescanPrechecked' to the 'continuescan' argument. That will
         * set flag to true if all required keys are satisfied and false
         * otherwise.
         */
        (void) _bt_checkkeys(scan, itup, indnatts, dir,
-                            &requiredMatchedByPrecheck, false);
+                            &continuescanPrechecked, false, false);
    }
    else
    {
-       requiredMatchedByPrecheck = false;
+       continuescanPrechecked = false;
    }
 
    if (ScanDirectionIsForward(dir))
            Assert(!BTreeTupleIsPivot(itup));
 
            passes_quals = _bt_checkkeys(scan, itup, indnatts, dir,
-                                        &continuescan, requiredMatchedByPrecheck);
+                                        &continuescan,
+                                        continuescanPrechecked,
+                                        haveFirstMatch);
 
            /*
             * If the result of prechecking required keys was true, then in
             * assert-enabled builds we also recheck that the _bt_checkkeys()
             * result is the same.
             */
-           Assert(!requiredMatchedByPrecheck ||
+           Assert((!continuescanPrechecked && haveFirstMatch) ||
                   passes_quals == _bt_checkkeys(scan, itup, indnatts, dir,
-                                                &continuescan, false));
+                                                &continuescan, false, false));
            if (passes_quals)
            {
                /* tuple passes all scan key conditions */
+               haveFirstMatch = true;
                if (!BTreeTupleIsPosting(itup))
                {
                    /* Remember it */
            int         truncatt;
 
            truncatt = BTreeTupleGetNAtts(itup, scan->indexRelation);
-           _bt_checkkeys(scan, itup, truncatt, dir, &continuescan, false);
+           _bt_checkkeys(scan, itup, truncatt, dir, &continuescan, false, false);
        }
 
        if (!continuescan)
            Assert(!BTreeTupleIsPivot(itup));
 
            passes_quals = _bt_checkkeys(scan, itup, indnatts, dir,
-                                        &continuescan, requiredMatchedByPrecheck);
+                                        &continuescan,
+                                        continuescanPrechecked,
+                                        haveFirstMatch);
 
            /*
             * If the result of prechecking required keys was true, then in
             * assert-enabled builds we also recheck that the _bt_checkkeys()
             * result is the same.
             */
-           Assert(!requiredMatchedByPrecheck ||
+           Assert((!continuescanPrechecked && !haveFirstMatch) ||
                   passes_quals == _bt_checkkeys(scan, itup, indnatts, dir,
-                                                &continuescan, false));
+                                                &continuescan, false, false));
            if (passes_quals && tuple_alive)
            {
                /* tuple passes all scan key conditions */
+               haveFirstMatch = true;
                if (!BTreeTupleIsPosting(itup))
                {
                    /* Remember it */
 
  * tupnatts: number of attributes in tupnatts (high key may be truncated)
  * dir: direction we are scanning in
  * continuescan: output parameter (will be set correctly in all cases)
- * requiredMatchedByPrecheck: indicates that scan keys required for
- *                               direction scan are already matched
+ * continuescanPrechecked: indicates that *continuescan flag is known to
+ *                            be true for the last item on the page
+ * haveFirstMatch: indicates that we already have at least one match
+ *                               in the current page
  */
 bool
 _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple, int tupnatts,
              ScanDirection dir, bool *continuescan,
-             bool requiredMatchedByPrecheck)
+             bool continuescanPrechecked, bool haveFirstMatch)
 {
    TupleDesc   tupdesc;
    BTScanOpaque so;
            requiredOppositeDir = true;
 
        /*
-        * Is the key required for scanning for either forward or backward
-        * direction?  If so and caller told us that these types of keys are
-        * known to be matched, skip the check.  Except for the row keys,
-        * where NULLs could be found in the middle of matching values.
+        * If the caller told us the *continuescan flag is known to be true
+        * for the last item on the page, then we know the keys required for
+        * the current direction scan should be matched.  Otherwise, the
+        * *continuescan flag would be set for the current item and
+        * subsequently the last item on the page accordingly.
+        *
+        * If the key is required for the opposite direction scan, we can skip
+        * the check if the caller tells us there was already at least one
+        * matching item on the page. Also, we require the *continuescan flag
+        * to be true for the last item on the page to know there are no
+        * NULLs.
+        *
+        * Both cases above work except for the row keys, where NULLs could be
+        * found in the middle of matching values.
         */
-       if ((requiredSameDir || requiredOppositeDir) &&
-           !(key->sk_flags & SK_ROW_HEADER) && requiredMatchedByPrecheck)
+       if ((requiredSameDir || (requiredOppositeDir && haveFirstMatch)) &&
+           !(key->sk_flags & SK_ROW_HEADER) && continuescanPrechecked)
            continue;
 
        if (key->sk_attno > tupnatts)
        }
 
        /*
-        * Apply the key checking function.  When the key is required for
-        * opposite direction scan, it must be already satisfied by
-        * _bt_first() except for the NULLs checking, which have already done
-        * above.
+        * Apply the key-checking function.  When the key is required for the
+        * opposite direction scan, it must be already satisfied as soon as
+        * there is already match on the page.  Except for the NULLs checking,
+        * which have already done above.
         */
-       if (!requiredOppositeDir)
+       if (!(requiredOppositeDir && haveFirstMatch))
        {
            test = FunctionCall2Coll(&key->sk_func, key->sk_collation,
                                     datum, key->sk_argument);