/* Next expected block, for detecting sequential access. */
    BlockNumber seq_blocknum;
+   BlockNumber seq_until_processed;
 
    /* The read operation we are currently preparing. */
    BlockNumber pending_read_blocknum;
  * distance to a level that prevents look-ahead until buffers are released.
  */
 static bool
-read_stream_start_pending_read(ReadStream *stream, bool suppress_advice)
+read_stream_start_pending_read(ReadStream *stream)
 {
    bool        need_wait;
    int         nblocks;
    else
        Assert(stream->next_buffer_index == stream->oldest_buffer_index);
 
-   /*
-    * If advice hasn't been suppressed, this system supports it, and this
-    * isn't a strictly sequential pattern, then we'll issue advice.
-    */
-   if (!suppress_advice &&
-       stream->advice_enabled &&
-       stream->pending_read_blocknum != stream->seq_blocknum)
-       flags = READ_BUFFERS_ISSUE_ADVICE;
-   else
-       flags = 0;
+   /* Do we need to issue read-ahead advice? */
+   flags = 0;
+   if (stream->advice_enabled)
+   {
+       if (stream->pending_read_blocknum == stream->seq_blocknum)
+       {
+           /*
+            * Sequential:  Issue advice until the preadv() calls have caught
+            * up with the first advice issued for this sequential region, and
+            * then stay of the way of the kernel's own read-ahead.
+            */
+           if (stream->seq_until_processed != InvalidBlockNumber)
+               flags = READ_BUFFERS_ISSUE_ADVICE;
+       }
+       else
+       {
+           /*
+            * Random jump:  Note the starting location of a new potential
+            * sequential region and start issuing advice.  Skip it this time
+            * if the preadv() follows immediately, eg first block in stream.
+            */
+           stream->seq_until_processed = stream->pending_read_blocknum;
+           if (stream->pinned_buffers > 0)
+               flags = READ_BUFFERS_ISSUE_ADVICE;
+       }
+   }
 
    /* How many more buffers is this backend allowed? */
    if (stream->temporary)
 }
 
 static void
-read_stream_look_ahead(ReadStream *stream, bool suppress_advice)
+read_stream_look_ahead(ReadStream *stream)
 {
    while (stream->ios_in_progress < stream->max_ios &&
           stream->pinned_buffers + stream->pending_read_nblocks < stream->distance)
 
        if (stream->pending_read_nblocks == stream->io_combine_limit)
        {
-           read_stream_start_pending_read(stream, suppress_advice);
-           suppress_advice = false;
+           read_stream_start_pending_read(stream);
            continue;
        }
 
        /* We have to start the pending read before we can build another. */
        while (stream->pending_read_nblocks > 0)
        {
-           if (!read_stream_start_pending_read(stream, suppress_advice) ||
+           if (!read_stream_start_pending_read(stream) ||
                stream->ios_in_progress == stream->max_ios)
            {
                /* We've hit the buffer or I/O limit.  Rewind and stop here. */
                read_stream_unget_block(stream, blocknum);
                return;
            }
-
-           suppress_advice = false;
        }
 
        /* This is the start of a new pending read. */
          stream->pinned_buffers == 0) ||
         stream->distance == 0) &&
        stream->ios_in_progress < stream->max_ios)
-       read_stream_start_pending_read(stream, suppress_advice);
+       read_stream_start_pending_read(stream);
 
    /*
     * There should always be something pinned when we leave this function,
    stream->callback = callback;
    stream->callback_private_data = callback_private_data;
    stream->buffered_blocknum = InvalidBlockNumber;
+   stream->seq_blocknum = InvalidBlockNumber;
+   stream->seq_until_processed = InvalidBlockNumber;
    stream->temporary = SmgrIsTemp(smgr);
 
    /*
         * space for more, but if we're just starting up we'll need to crank
         * the handle to get started.
         */
-       read_stream_look_ahead(stream, true);
+       read_stream_look_ahead(stream);
 
        /* End of stream reached? */
        if (stream->pinned_buffers == 0)
                stream->distance = distance;
            }
        }
+
+       /*
+        * If we've reached the first block of a sequential region we're
+        * issuing advice for, cancel that until the next jump.  The kernel
+        * will see the sequential preadv() pattern starting here.
+        */
+       if (stream->advice_enabled &&
+           stream->ios[io_index].op.blocknum == stream->seq_until_processed)
+           stream->seq_until_processed = InvalidBlockNumber;
    }
 
 #ifdef CLOBBER_FREED_MEMORY
        stream->oldest_buffer_index = 0;
 
    /* Prepare for the next call. */
-   read_stream_look_ahead(stream, false);
+   read_stream_look_ahead(stream);
 
 #ifndef READ_STREAM_DISABLE_FAST_PATH
    /* See if we can take the fast path for all-cached scans next time. */